Author: Ronan Lamy <[email protected]>
Branch: py3k
Changeset: r85869:bb148d9bb7e9
Date: 2016-07-26 20:40 +0100
http://bitbucket.org/pypy/pypy/changeset/bb148d9bb7e9/
Log: hg merge default
diff --git a/dotviewer/graphparse.py b/dotviewer/graphparse.py
--- a/dotviewer/graphparse.py
+++ b/dotviewer/graphparse.py
@@ -85,10 +85,11 @@
pass
def splitline(line, re_word = re.compile(r'[^\s"]\S*|["]["]|["].*?[^\\]["]')):
+ import ast
result = []
for word in re_word.findall(line):
if word.startswith('"'):
- word = eval(word)
+ word = ast.literal_eval(word)
result.append(word)
return result
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -198,10 +198,13 @@
return tp._alignmentofinstances()
@builtinify
-def byref(cdata):
+def byref(cdata, offset=0):
# "pointer" is imported at the end of this module to avoid circular
# imports
- return pointer(cdata)
+ ptr = pointer(cdata)
+ if offset != 0:
+ ptr._buffer[0] += offset
+ return ptr
def cdata_from_address(self, address):
# fix the address: turn it into as unsigned, in case it's a negative number
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -335,3 +335,58 @@
This will disable SELinux's protection and allow PyPy to configure correctly.
Be sure to enable it again if you need it!
+
+
+How should I report a bug?
+--------------------------
+
+Our bug tracker is here: https://bitbucket.org/pypy/pypy/issues/
+
+Missing features or incompatibilities with CPython are considered
+bugs, and they are welcome. (See also our list of `known
+incompatibilities`__.)
+
+.. __: http://pypy.org/compat.html
+
+For bugs of the kind "I'm getting a PyPy crash or a strange
+exception", please note that: **We can't do anything without
+reproducing the bug ourselves**. We cannot do anything with
+tracebacks from gdb, or core dumps. This is not only because the
+standard PyPy is compiled without debug symbols. The real reason is
+that a C-level traceback is usually of no help at all in PyPy.
+Debugging PyPy can be annoying.
+
+In more details:
+
+* First, please give the exact PyPy version, and the OS.
+
+* It might help focus our search if we know if the bug can be
+ reproduced on a "``pypy --jit off``" or not. If "``pypy --jit
+ off``" always works, then the problem might be in the JIT.
+ Otherwise, we know we can ignore that part.
+
+* If you got the bug using only Open Source components, please give a
+ step-by-step guide that we can follow to reproduce the problem
+ ourselves. Don't assume we know anything about any program other
+ than PyPy. We would like a guide that we can follow point by point
+ (without guessing or having to figure things out)
+ on a machine similar to yours, starting from a bare PyPy, until we
+ see the same problem. (If you can, you can try to reduce the number
+ of steps and the time it needs to run, but that is not mandatory.)
+
+* If the bug involves Closed Source components, or just too many Open
+ Source components to install them all ourselves, then maybe you can
+ give us some temporary ssh access to a machine where the bug can be
+ reproduced.
+
+* If giving us access would require us to sign a NDA, then we can
+ consider a commerical support contract for a small sum of money.
+
+* If even that is not possible for you, then sorry, we can't help.
+
+Of course, you can try to debug the problem yourself, and we can help
+you get started if you ask on the #pypy IRC channel, but be prepared:
+debugging an annoying PyPy problem usually involves quite a lot of gdb
+in auto-generated C code, and at least some knowledge about the
+various components involved, from PyPy's own RPython source code to
+the GC and possibly the JIT.
diff --git a/pypy/module/_cffi_backend/ctypestruct.py
b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -90,7 +90,7 @@
self.force_lazy_struct()
space = self.space
try:
- cfield = self._fields_dict[fieldname]
+ cfield = self._getcfield_const(fieldname)
except KeyError:
raise OperationError(space.w_KeyError, space.wrap(fieldname))
if cfield.bitshift >= 0:
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2366,6 +2366,60 @@
(binaryfunc)NULL, /* nb_divide */
};
+static PyObject*
+array_base_multiply(PyObject* obj1, PyObject* obj2)
+{
+ if (PyList_Check(obj1) && ((arrayobject*)obj2)->ob_descr->typecode == 'i'
&& Py_SIZE(obj2) == 1)
+ {
+ int nn;
+ int n = PyList_Size(obj1);
+ PyObject *v = getarrayitem(obj2, 0);
+ int i = ((PyIntObject*)v)->ob_ival;
+ PyObject * ret = PyList_New(n);
+ for (nn = 0; nn < n; nn++)
+ {
+ v = PyList_GetItem(obj1, nn);
+ if (PyInt_Check(v))
+ PyList_SetItem(ret, nn, PyLong_FromLong(i *
((PyIntObject*)v)->ob_ival));
+ else
+ PyList_SetItem(ret, nn, v);
+ }
+ return ret;
+ }
+ else if (PyList_Check(obj2) && ((arrayobject*)obj1)->ob_descr->typecode ==
'i' && Py_SIZE(obj1) == 1)
+ {
+ int nn;
+ int n = PyList_Size(obj2);
+ PyObject *v = getarrayitem(obj1, 0);
+ int i = ((PyIntObject*)v)->ob_ival;
+ PyObject * ret = PyList_New(n);
+ for (nn = 0; nn < n; nn++)
+ {
+ v = PyList_GetItem(obj2, nn);
+ if (PyInt_Check(v))
+ PyList_SetItem(ret, nn, PyLong_FromLong(i *
((PyIntObject*)v)->ob_ival));
+ else
+ PyList_SetItem(ret, nn, v);
+ }
+ return ret;
+ }
+ else if(obj1->ob_type == &Arraytype)
+ fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
+ ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name);
+ else if(obj2->ob_type == &Arraytype)
+ fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
+ ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name);
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+
+static PyNumberMethods array_base_as_number = {
+ (binaryfunc)NULL, /* nb_add*/
+ (binaryfunc)NULL, /* nb_subtract */
+ (binaryfunc)array_base_multiply, /* nb_multiply */
+ (binaryfunc)NULL, /* nb_divide */
+};
+
static PyMappingMethods array_as_mapping = {
(lenfunc)array_length,
(binaryfunc)array_subscr,
@@ -2624,6 +2678,49 @@
static PyObject *array_iter(arrayobject *ao);
+static PyTypeObject ArrayBasetype = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "array.basearray",
+ sizeof(arrayobject),
+ 0,
+ (destructor)array_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)array_repr, /* tp_repr */
+ &array_base_as_number, /* tp_as_number*/
+ &array_as_sequence, /* tp_as_sequence*/
+ &array_as_mapping, /* tp_as_mapping*/
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ &array_as_buffer, /* tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
+ arraytype_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ array_richcompare, /* tp_richcompare */
+ offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
+ (getiterfunc)array_iter, /* tp_iter */
+ 0, /* tp_iternext */
+ array_methods, /* tp_methods */
+ 0, /* tp_members */
+ array_getsets, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ PyType_GenericAlloc, /* tp_alloc */
+ array_new, /* tp_new */
+ PyObject_Del, /* tp_free */
+};
+
static PyTypeObject Arraytype = {
PyVarObject_HEAD_INIT(NULL, 0)
"array.array",
@@ -2791,6 +2888,8 @@
register Py_UNICODE *p;
struct arraydescr *descr;
+ ArrayBasetype.ob_type = &PyType_Type;
+ Arraytype.tp_base = &ArrayBasetype;
if (PyType_Ready(&Arraytype) < 0)
return NULL;
Py_TYPE(&PyArrayIter_Type) = &PyType_Type;
@@ -2798,10 +2897,11 @@
if (m == NULL)
return NULL;
- Py_INCREF((PyObject *)&Arraytype);
+ if (PyType_Ready(&ArrayBasetype) < 0)
+ return;
PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype);
- Py_INCREF((PyObject *)&Arraytype);
PyModule_AddObject(m, "array", (PyObject *)&Arraytype);
+ PyModule_AddObject(m, "arraybase", (PyObject *)&ArrayBasetype);
for (descr=descriptors; descr->typecode != '\0'; descr++) {
size++;
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -747,6 +747,7 @@
if (PyType_Ready(&UnicodeSubtype3) < 0)
INITERROR;
+ TupleLike.tp_flags = Py_TPFLAGS_DEFAULT;
TupleLike.tp_base = &PyTuple_Type;
if (PyType_Ready(&TupleLike) < 0)
INITERROR;
diff --git a/pypy/module/cpyext/test/test_bytesobject.py
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -113,9 +113,10 @@
module = self.import_extension('foo', [
("getbytes", "METH_NOARGS",
"""
- PyObject* s1 = PyBytes_FromStringAndSize("test", 4);
- char* c = PyBytes_AsString(s1);
- PyObject* s2 = PyBytes_FromStringAndSize(c, 4);
+ char *c;
+ PyObject* s2, *s1 = PyBytes_FromStringAndSize("test", 4);
+ c = PyBytes_AsString(s1);
+ s2 = PyBytes_FromStringAndSize(c, 4);
Py_DECREF(s1);
return s2;
"""),
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -78,7 +78,7 @@
else:
libraries = []
if sys.platform.startswith('linux'):
- compile_extra = ["-Werror", "-g", "-O0", "-fPIC"]
+ compile_extra = ["-Werror", "-g", "-O0", "-Wp,-U_FORTIFY_SOURCE",
"-fPIC"]
link_extra = ["-g"]
else:
compile_extra = link_extra = None
@@ -129,6 +129,7 @@
return str(soname)
def freeze_refcnts(self):
+ rawrefcount._dont_free_any_more()
return #ZZZ
state = self.space.fromcache(RefcountState)
self.frozen_refcounts = {}
diff --git a/pypy/module/itertools/interp_itertools.py
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -803,7 +803,7 @@
data before the other iterator, it is faster to use list() instead
of tee()
- Equivalent to :
+ If iter(iterable) has no method __copy__(), this is equivalent to:
def tee(iterable, n=2):
def gen(next, data={}, cnt=[0]):
@@ -816,17 +816,22 @@
yield item
it = iter(iterable)
return tuple([gen(it.next) for i in range(n)])
+
+ If iter(iterable) has a __copy__ method, though, we just return
+ a tuple t = (iterable, t[0].__copy__(), t[1].__copy__(), ...).
"""
if n < 0:
raise oefmt(space.w_ValueError, "n must be >= 0")
- if isinstance(w_iterable, W_TeeIterable): # optimization only
- w_chained_list = w_iterable.w_chained_list
- w_iterator = w_iterable.w_iterator
+ if space.findattr(w_iterable, space.wrap("__copy__")) is not None:
+ # In this case, we don't instantiate any W_TeeIterable.
+ # We just rely on doing repeated __copy__(). This case
+ # includes the situation where w_iterable is already
+ # a W_TeeIterable itself.
iterators_w = [w_iterable] * n
for i in range(1, n):
- iterators_w[i] = space.wrap(W_TeeIterable(space, w_iterator,
- w_chained_list))
+ w_iterable = space.call_method(w_iterable, "__copy__")
+ iterators_w[i] = w_iterable
else:
w_iterator = space.iter(w_iterable)
w_chained_list = W_TeeChainedListNode(space)
@@ -905,6 +910,11 @@
self.w_chained_list = w_chained_list.w_next
return w_obj
+ def copy_w(self):
+ space = self.space
+ tee_iter = W_TeeIterable(space, self.w_iterator, self.chained_list)
+ return space.wrap(tee_iter)
+
def reduce_w(self):
return self.space.newtuple([self.space.gettypefor(W_TeeIterable),
self.space.newtuple([self.space.newtuple([])]),
@@ -943,6 +953,7 @@
__new__ = interp2app(W_TeeIterable___new__),
__iter__ = interp2app(W_TeeIterable.iter_w),
__next__ = interp2app(W_TeeIterable.next_w),
+ __copy__ = interp2app(W_TeeIterable.copy_w),
__weakref__ = make_weakref_descr(W_TeeIterable),
__reduce__ = interp2app(W_TeeIterable.reduce_w),
__setstate__ = interp2app(W_TeeIterable.setstate_w)
diff --git a/pypy/module/itertools/test/test_itertools.py
b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -577,6 +577,48 @@
x = next(d)
assert x == 'b'
+ def test_tee_defines_copy(self):
+ import itertools
+ a, b = itertools.tee('abc')
+ c = b.__copy__()
+ assert list(a) == ['a', 'b', 'c']
+ assert list(b) == ['a', 'b', 'c']
+ assert list(c) == ['a', 'b', 'c']
+ a, = itertools.tee('abc', 1)
+ x = a.next()
+ assert x == 'a'
+ b = a.__copy__()
+ x = a.next()
+ assert x == 'b'
+ x = b.next()
+ assert x == 'b'
+
+ def test_tee_function_uses_copy(self):
+ import itertools
+ class MyIterator(object):
+ def __iter__(self):
+ return self
+ def next(self):
+ raise NotImplementedError
+ def __copy__(self):
+ return iter('def')
+ my = MyIterator()
+ a, = itertools.tee(my, 1)
+ assert a is my
+ a, b = itertools.tee(my)
+ assert a is my
+ assert b is not my
+ assert list(b) == ['d', 'e', 'f']
+ # this gives AttributeError because it tries to call
+ # my.__copy__().__copy__() and there isn't one
+ raises(AttributeError, itertools.tee, my, 3)
+
+ def test_tee_function_empty(self):
+ import itertools
+ assert itertools.tee('abc', 0) == ()
+ a, = itertools.tee('abc', 1)
+ assert itertools.tee(a, 0) == ()
+
class AppTestItertools26:
spaceconfig = dict(usemodules=['itertools'])
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
@@ -265,3 +265,10 @@
class A(object):
_byref = byref
A._byref(c_int(5))
+
+ def test_byref_with_offset(self):
+ c = c_int()
+ d = byref(c)
+ base = cast(d, c_void_p).value
+ for i in [0, 1, 4, 1444, -10293]:
+ assert cast(byref(c, i), c_void_p).value == base + i
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -205,6 +205,9 @@
def newbytes(self, x):
return w_some_obj()
+ def newunicode(self, x):
+ return w_some_obj()
+
def wrap(self, x):
if not we_are_translated():
if isinstance(x, gateway.interp2app):
diff --git a/rpython/jit/backend/arm/test/test_assembler.py
b/rpython/jit/backend/arm/test/test_assembler.py
--- a/rpython/jit/backend/arm/test/test_assembler.py
+++ b/rpython/jit/backend/arm/test/test_assembler.py
@@ -1,6 +1,5 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
-from rpython.jit.backend.arm.support import arm_int_div
from rpython.jit.backend.arm.assembler import AssemblerARM
from rpython.jit.backend.arm.locations import imm
from rpython.jit.backend.arm.test.support import run_asm
@@ -180,19 +179,6 @@
self.a.gen_func_epilog()
assert run_asm(self.a) == 133
- def test_division(self):
- self.a.gen_func_prolog()
- self.a.mc.MOV_ri(r.r0.value, 123)
- self.a.mc.MOV_ri(r.r1.value, 2)
-
- # call to div
- self.a.mc.PUSH(range(2, 12))
- div_addr = rffi.cast(lltype.Signed, arm_int_div)
- self.a.mc.BL(div_addr)
- self.a.mc.POP(range(2, 12))
- self.a.gen_func_epilog()
- assert run_asm(self.a) == 61
-
def test_bl_with_conditional_exec(self):
functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
diff --git a/rpython/jit/backend/arm/test/test_regalloc.py
b/rpython/jit/backend/arm/test/test_regalloc.py
--- a/rpython/jit/backend/arm/test/test_regalloc.py
+++ b/rpython/jit/backend/arm/test/test_regalloc.py
@@ -545,23 +545,6 @@
self.interpret(ops, [s, 1234567890])
assert s[1] == 1234567890
- def test_division_optimized(self):
- ops = '''
- [i7, i6]
- label(i7, i6, descr=targettoken)
- i18 = int_floordiv(i7, i6)
- i19 = int_xor(i7, i6)
- i21 = int_lt(i19, 0)
- i22 = int_mod(i7, i6)
- i23 = int_is_true(i22)
- i24 = int_eq(i6, 4)
- guard_false(i24) [i18]
- jump(i18, i6, descr=targettoken)
- '''
- self.interpret(ops, [10, 4])
- assert self.getint(0) == 2
- # FIXME: Verify that i19 - i23 are removed
-
class TestRegallocFloats(CustomBaseTestRegalloc):
def test_float_add(self):
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py
b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -330,6 +330,13 @@
expected_size = 2
idx = 1
fixed_size -= 32
+ if self.cpu.backend_name.startswith('zarch') or \
+ self.cpu.backend_name.startswith('ppc'):
+ # the allocation always allocates the register
+ # into the return register. (e.g. r3 on ppc)
+ # the next malloc_nursery will move r3 to the
+ # frame manager, thus the two bits will be on the frame
+ fixed_size += 4
assert len(frame.jf_gcmap) == expected_size
# check that we have two bits set, and that they are in two
# registers (p0 and p1 are moved away when doing p2, but not
diff --git a/rpython/jit/backend/zarch/arch.py
b/rpython/jit/backend/zarch/arch.py
--- a/rpython/jit/backend/zarch/arch.py
+++ b/rpython/jit/backend/zarch/arch.py
@@ -45,10 +45,7 @@
# +------------------------------+ <- assembler begin
# | SAVE CONTEXT |
# +------------------------------+
-# +--+| BRANCH (saves addr of pool |
-# | | in r13) |
-# | +------------------------------+
-# | | ... |
+#start| ... |
# | | LITERAL POOL | <---+
# | | ... | <-+ |
# +-->+------------------------------+ | |
diff --git a/rpython/jit/backend/zarch/assembler.py
b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -309,17 +309,15 @@
# signature of this _frame_realloc_slowpath function:
# * on entry, r0 is the new size
- # * on entry, r1 is the gcmap
# * no managed register must be modified
- ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
- mc.STG(r.SCRATCH, l.addr(ofs2, r.SPP))
+ # caller already did push_gcmap(store=True)
self._push_core_regs_to_jitframe(mc, r.MANAGED_REGS)
self._push_fp_regs_to_jitframe(mc)
- # First argument is SPP (= r31), which is the jitframe
+ # First argument is SPP, which is the jitframe
mc.LGR(r.r2, r.SPP)
# no need to move second argument (frame_depth),
@@ -347,6 +345,7 @@
mc.load(r.r5, r.r5, 0)
mc.store(r.r2, r.r5, -WORD)
+ self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller
self._pop_core_regs_from_jitframe(mc, r.MANAGED_REGS)
self._pop_fp_regs_from_jitframe(mc)
@@ -386,14 +385,12 @@
# signature of these cond_call_slowpath functions:
# * on entry, r11 contains the function to call
# * r2, r3, r4, r5 contain arguments for the call
- # * r0 is the gcmap
+ # * gcmap is pushed
# * the old value of these regs must already be stored in the
jitframe
# * on exit, all registers are restored from the jitframe
mc = InstrBuilder()
self.mc = mc
- ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
- mc.STG(r.SCRATCH2, l.addr(ofs2,r.SPP))
mc.store_link()
mc.push_std_frame()
@@ -411,6 +408,7 @@
reg is not r.r4 and
reg is not r.r5 and
reg is not r.r11]
+ # the caller already did push_gcmap(store=True)
self._push_core_regs_to_jitframe(mc, regs)
if supports_floats:
self._push_fp_regs_to_jitframe(mc)
@@ -420,6 +418,7 @@
# Finish
self._reload_frame_if_necessary(mc)
+ self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller
self._pop_core_regs_from_jitframe(mc, saved_regs)
if supports_floats:
self._pop_fp_regs_from_jitframe(mc)
@@ -449,12 +448,11 @@
mc.store_link()
mc.push_std_frame()
#
- ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
- mc.STG(r.r1, l.addr(ofs2, r.SPP))
saved_regs = [reg for reg in r.MANAGED_REGS
if reg is not r.RES and reg is not r.RSZ]
self._push_core_regs_to_jitframe(mc, saved_regs)
self._push_fp_regs_to_jitframe(mc)
+ # the caller already did push_gcmap(store=True)
#
if kind == 'fixed':
addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
@@ -588,7 +586,7 @@
# sum -> (14 bytes)
mc.write('\x00'*14)
mc.load_imm(r.RETURN, self._frame_realloc_slowpath)
- self.load_gcmap(mc, r.r1, gcmap)
+ self.push_gcmap(mc, gcmap, store=True)
mc.raw_call()
self.frame_depth_to_patch.append((patch_pos, mc.currpos()))
@@ -685,6 +683,8 @@
# name = "Loop # %s: %s" % (looptoken.number, loopname)
# self.cpu.profile_agent.native_code_written(name,
# rawstart, full_size)
+ #print(hex(rawstart+looppos))
+ #import pdb; pdb.set_trace()
return AsmInfo(ops_offset, rawstart + looppos,
size_excluding_failure_stuff - looppos, rawstart)
@@ -867,6 +867,10 @@
ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
mc.STG(r.SCRATCH, l.addr(ofs, r.SPP))
+ def pop_gcmap(self, mc):
+ ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+ mc.LG(r.SCRATCH, l.addr(ofs, r.SPP))
+
def break_long_loop(self):
# If the loop is too long, the guards in it will jump forward
# more than 32 KB. We use an approximate hack to know if we
@@ -1339,7 +1343,7 @@
# new value of nursery_free_adr in RSZ and the adr of the new object
# in RES.
- self.load_gcmap(mc, r.r1, gcmap)
+ self.push_gcmap(mc, gcmap, store=True)
mc.branch_absolute(self.malloc_slowpath)
# here r1 holds nursery_free_addr
@@ -1375,7 +1379,7 @@
# new value of nursery_free_adr in RSZ and the adr of the new object
# in RES.
- self.load_gcmap(mc, r.r1, gcmap)
+ self.push_gcmap(mc, gcmap, store=True)
mc.branch_absolute(self.malloc_slowpath)
offset = mc.currpos() - fast_jmp_pos
@@ -1468,7 +1472,7 @@
pmc.overwrite()
#
# save the gcmap
- self.load_gcmap(mc, r.r1, gcmap)
+ self.push_gcmap(mc, gcmap, store=True)
#
# load the function into r14 and jump
if kind == rewrite.FLAG_ARRAY:
diff --git a/rpython/jit/backend/zarch/opassembler.py
b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -387,8 +387,7 @@
if reg in self._COND_CALL_SAVE_REGS]
self._push_core_regs_to_jitframe(self.mc, should_be_saved)
- # load gc map into unusual location: r0
- self.load_gcmap(self.mc, r.SCRATCH2, regalloc.get_gcmap())
+ self.push_gcmap(self.mc, regalloc.get_gcmap())
#
# load the 0-to-4 arguments into these registers, with the address of
# the function to call into r11
diff --git a/rpython/jit/backend/zarch/test/test_runner.py
b/rpython/jit/backend/zarch/test/test_runner.py
--- a/rpython/jit/backend/zarch/test/test_runner.py
+++ b/rpython/jit/backend/zarch/test/test_runner.py
@@ -26,4 +26,4 @@
add_loop_instructions = "lg; lgr; larl; agr; cgfi; jge; j;$"
bridge_loop_instructions = "lg; cgfi; jnl; lghi; " \
- "(lgfi|iilf);( iihf;)? (lgfi|iilf);( iihf;)?
basr; larl; (lgfi|iilf);( iihf;)? br;$"
+ "(lgfi|iilf);( iihf;)? (lgfi|iilf);( iihf;)?
stg; basr; larl; (lgfi|iilf);( iihf;)? br;$"
diff --git a/rpython/jit/metainterp/blackhole.py
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1143,45 +1143,35 @@
@arguments("cpu", "i", "R", "d", returns="i")
def bhimpl_residual_call_r_i(cpu, func, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_i(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "R", "d", returns="r")
def bhimpl_residual_call_r_r(cpu, func, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_r(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "R", "d")
def bhimpl_residual_call_r_v(cpu, func, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_v(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d", returns="i")
def bhimpl_residual_call_ir_i(cpu, func, args_i, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_i(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d", returns="r")
def bhimpl_residual_call_ir_r(cpu, func, args_i, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_r(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d")
def bhimpl_residual_call_ir_v(cpu, func, args_i, args_r, calldescr):
- workaround2200.active = True
return cpu.bh_call_v(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="i")
def bhimpl_residual_call_irf_i(cpu, func, args_i,args_r,args_f,calldescr):
- workaround2200.active = True
return cpu.bh_call_i(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="r")
def bhimpl_residual_call_irf_r(cpu, func, args_i,args_r,args_f,calldescr):
- workaround2200.active = True
return cpu.bh_call_r(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="f")
def bhimpl_residual_call_irf_f(cpu, func, args_i,args_r,args_f,calldescr):
- workaround2200.active = True
return cpu.bh_call_f(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d")
def bhimpl_residual_call_irf_v(cpu, func, args_i,args_r,args_f,calldescr):
- workaround2200.active = True
return cpu.bh_call_v(func, args_i, args_r, args_f, calldescr)
# conditional calls - note that they cannot return stuff
@@ -1209,54 +1199,44 @@
@arguments("cpu", "j", "R", returns="i")
def bhimpl_inline_call_r_i(cpu, jitcode, args_r):
- workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "R", returns="r")
def bhimpl_inline_call_r_r(cpu, jitcode, args_r):
- workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "R")
def bhimpl_inline_call_r_v(cpu, jitcode, args_r):
- workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", returns="i")
def bhimpl_inline_call_ir_i(cpu, jitcode, args_i, args_r):
- workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", returns="r")
def bhimpl_inline_call_ir_r(cpu, jitcode, args_i, args_r):
- workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R")
def bhimpl_inline_call_ir_v(cpu, jitcode, args_i, args_r):
- workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="i")
def bhimpl_inline_call_irf_i(cpu, jitcode, args_i, args_r, args_f):
- workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="r")
def bhimpl_inline_call_irf_r(cpu, jitcode, args_i, args_r, args_f):
- workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="f")
def bhimpl_inline_call_irf_f(cpu, jitcode, args_i, args_r, args_f):
- workaround2200.active = True
return cpu.bh_call_f(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F")
def bhimpl_inline_call_irf_v(cpu, jitcode, args_i, args_r, args_f):
- workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@@ -1543,8 +1523,6 @@
if not self.nextblackholeinterp:
self._exit_frame_with_exception(current_exc)
return current_exc
- finally:
- workaround2200.active = False
#
# pass the frame's return value to the caller
caller = self.nextblackholeinterp
@@ -1717,10 +1695,3 @@
#
_run_forever(firstbh, current_exc)
convert_and_run_from_pyjitpl._dont_inline_ = True
-
-# ____________________________________________________________
-
-class WorkaroundIssue2200(object):
- pass
-workaround2200 = WorkaroundIssue2200()
-workaround2200.active = False
diff --git a/rpython/jit/metainterp/compile.py
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -620,23 +620,28 @@
raise jitexc.DoneWithThisFrameVoid()
class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr):
+ def get_result(self, cpu, deadframe):
+ return cpu.get_int_value(deadframe, 0)
def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
assert jitdriver_sd.result_type == history.INT
- result = metainterp_sd.cpu.get_int_value(deadframe, 0)
- raise jitexc.DoneWithThisFrameInt(result)
+ cpu = metainterp_sd.cpu
+ raise jitexc.DoneWithThisFrameInt(self.get_result(cpu, deadframe))
class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr):
+ def get_result(self, cpu, deadframe):
+ return cpu.get_ref_value(deadframe, 0)
def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
assert jitdriver_sd.result_type == history.REF
cpu = metainterp_sd.cpu
- result = cpu.get_ref_value(deadframe, 0)
- raise jitexc.DoneWithThisFrameRef(cpu, result)
+ raise jitexc.DoneWithThisFrameRef(cpu, self.get_result(cpu, deadframe))
class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr):
+ def get_result(self, cpu, deadframe):
+ return cpu.get_float_value(deadframe, 0)
def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
assert jitdriver_sd.result_type == history.FLOAT
- result = metainterp_sd.cpu.get_float_value(deadframe, 0)
- raise jitexc.DoneWithThisFrameFloat(result)
+ cpu = metainterp_sd.cpu
+ raise jitexc.DoneWithThisFrameFloat(self.get_result(cpu, deadframe))
class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr):
def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
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
@@ -57,10 +57,16 @@
self.cache_anything = {}
self.cache_seen_allocation = {}
+ # set of boxes that we've seen a quasi-immut for the field on. cleared
+ # on writes to the field.
+ self.quasiimmut_seen = None
+
def _clear_cache_on_write(self, seen_allocation_of_target):
if not seen_allocation_of_target:
self.cache_seen_allocation.clear()
self.cache_anything.clear()
+ if self.quasiimmut_seen is not None:
+ self.quasiimmut_seen.clear()
def _seen_alloc(self, ref_box):
if not isinstance(ref_box, RefFrontendOp):
@@ -92,6 +98,8 @@
def invalidate_unescaped(self):
self._invalidate_unescaped(self.cache_anything)
self._invalidate_unescaped(self.cache_seen_allocation)
+ if self.quasiimmut_seen is not None:
+ self.quasiimmut_seen.clear()
def _invalidate_unescaped(self, d):
for ref_box in d.keys():
@@ -484,3 +492,18 @@
if isinstance(oldbox, FrontendOp) and isinstance(newbox, Const):
assert newbox.same_constant(constant_from_op(oldbox))
oldbox.set_replaced_with_const()
+
+ def is_quasi_immut_known(self, fielddescr, box):
+ cache = self.heap_cache.get(fielddescr, None)
+ if cache is not None and cache.quasiimmut_seen is not None:
+ return box in cache.quasiimmut_seen
+ return False
+
+ def quasi_immut_now_known(self, fielddescr, box):
+ cache = self.heap_cache.get(fielddescr, None)
+ if cache is None:
+ cache = self.heap_cache[fielddescr] = CacheEntry(self)
+ if cache.quasiimmut_seen is not None:
+ cache.quasiimmut_seen[box] = None
+ else:
+ cache.quasiimmut_seen = {box: None}
diff --git a/rpython/jit/metainterp/optimizeopt/intdiv.py
b/rpython/jit/metainterp/optimizeopt/intdiv.py
--- a/rpython/jit/metainterp/optimizeopt/intdiv.py
+++ b/rpython/jit/metainterp/optimizeopt/intdiv.py
@@ -1,5 +1,5 @@
from rpython.rlib.rarithmetic import LONG_BIT, intmask, r_uint
-from rpython.rlib.rbigint import rbigint, ONERBIGINT
+
from rpython.jit.metainterp.history import ConstInt
from rpython.jit.metainterp.resoperation import ResOperation, rop
@@ -17,10 +17,19 @@
while (r_uint(1) << (i+1)) < r_uint(m):
i += 1
- # k = 2**(64+i) // m + 1, computed manually using rbigint
- # because that's the easiest
- k1 = ONERBIGINT.lshift(LONG_BIT + i).floordiv(rbigint.fromint(m))
- k = k1.touint() + r_uint(1)
+ # quotient = 2**(64+i) // m
+ high_word_dividend = r_uint(1) << i
+ quotient = r_uint(0)
+ for bit in range(LONG_BIT-1, -1, -1):
+ t = quotient + (r_uint(1) << bit)
+ # check: is 't * m' small enough to be < 2**(64+i), or not?
+ # note that we're really computing (2**(64+i)-1) // m, but the result
+ # is the same, because powers of two are not multiples of m.
+ if unsigned_mul_high(t, r_uint(m)) < high_word_dividend:
+ quotient = t # yes, small enough
+
+ # k = 2**(64+i) // m + 1
+ k = quotient + r_uint(1)
assert k != r_uint(0)
# Proof that k < 2**64 holds in all cases, even with the "+1":
diff --git a/rpython/jit/metainterp/pyjitpl.py
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -829,8 +829,11 @@
mutatefielddescr, orgpc):
from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
cpu = self.metainterp.cpu
+ if self.metainterp.heapcache.is_quasi_immut_known(fielddescr, box):
+ return
descr = QuasiImmutDescr(cpu, box.getref_base(), fielddescr,
mutatefielddescr)
+ self.metainterp.heapcache.quasi_immut_now_known(fielddescr, box)
self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
None, descr=descr)
self.metainterp.generate_guard(rop.GUARD_NOT_INVALIDATED,
@@ -2540,7 +2543,13 @@
elif box.type == history.REF: args.append(box.getref_base())
elif box.type == history.FLOAT: args.append(box.getfloatstorage())
else: assert 0
- self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args)
+ res = self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args)
+ kind = history.getkind(lltype.typeOf(res))
+ if kind == 'void': raise jitexc.DoneWithThisFrameVoid()
+ if kind == 'int': raise jitexc.DoneWithThisFrameInt(res)
+ if kind == 'ref': raise jitexc.DoneWithThisFrameRef(self.cpu, res)
+ if kind == 'float': raise jitexc.DoneWithThisFrameFloat(res)
+ raise AssertionError(kind)
def prepare_resume_from_failure(self, deadframe, inputargs, resumedescr):
exception = self.cpu.grab_exc_value(deadframe)
diff --git a/rpython/jit/metainterp/test/test_ajit.py
b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -4470,6 +4470,28 @@
self.meta_interp(f, [])
+ def test_issue2335_recursion(self):
+ # Reproduces issue #2335: same as issue #2200, but the workaround
+ # in c4c54cb69aba was not enough.
+ driver = JitDriver(greens=["level"], reds=["i"])
+ def enter(level, i):
+ if level == 0:
+ f(1) # recursive call
+ driver.can_enter_jit(level=level, i=i)
+ def f(level):
+ i = 0 if level == 0 else 298
+ while True:
+ driver.jit_merge_point(level=level, i=i)
+ i += 1
+ if i >= 300:
+ return i
+ promote(i + 1) # a failing guard
+ enter(level, i)
+ def main():
+ set_param(None, 'trace_eagerness', 999999)
+ f(0)
+ self.meta_interp(main, [])
+
def test_pending_setarrayitem_with_indirect_constant_index(self):
driver = JitDriver(greens=[], reds='auto')
class X:
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
@@ -797,3 +797,46 @@
h.class_now_known(box1) # interaction of the two families of flags
assert not h.is_unescaped(box1)
assert h.is_likely_virtual(box1)
+
+ def test_quasiimmut_seen(self):
+ h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
+ assert not h.is_quasi_immut_known(descr1, box1)
+ assert not h.is_quasi_immut_known(descr1, box2)
+ assert not h.is_quasi_immut_known(descr2, box3)
+ assert not h.is_quasi_immut_known(descr2, box4)
+ h.quasi_immut_now_known(descr1, box1)
+ assert h.is_quasi_immut_known(descr1, box1)
+ assert not h.is_quasi_immut_known(descr1, box2)
+ assert not h.is_quasi_immut_known(descr2, box3)
+ assert not h.is_quasi_immut_known(descr2, box4)
+ h.quasi_immut_now_known(descr1, box2)
+ assert h.is_quasi_immut_known(descr1, box1)
+ assert h.is_quasi_immut_known(descr1, box2)
+ assert not h.is_quasi_immut_known(descr2, box3)
+ assert not h.is_quasi_immut_known(descr2, box4)
+ h.quasi_immut_now_known(descr2, box3)
+ assert h.is_quasi_immut_known(descr1, box1)
+ assert h.is_quasi_immut_known(descr1, box2)
+ assert h.is_quasi_immut_known(descr2, box3)
+ assert not h.is_quasi_immut_known(descr2, box4)
+ h.quasi_immut_now_known(descr2, box4)
+ assert h.is_quasi_immut_known(descr1, box1)
+ assert h.is_quasi_immut_known(descr1, box2)
+ assert h.is_quasi_immut_known(descr2, box3)
+ assert h.is_quasi_immut_known(descr2, box4)
+
+ # invalidate the descr1 cache
+
+ h.setfield(box1, box3, descr1)
+ assert not h.is_quasi_immut_known(descr1, box1)
+ assert not h.is_quasi_immut_known(descr1, box2)
+
+ # a call invalidates everything
+ h.invalidate_caches(
+ rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), [])
+ assert not h.is_quasi_immut_known(descr2, box3)
+ assert not h.is_quasi_immut_known(descr2, box4)
diff --git a/rpython/jit/metainterp/test/test_tracingopts.py
b/rpython/jit/metainterp/test/test_tracingopts.py
--- a/rpython/jit/metainterp/test/test_tracingopts.py
+++ b/rpython/jit/metainterp/test/test_tracingopts.py
@@ -512,6 +512,32 @@
assert res == 4 * 7
self.check_operations_history(getfield_gc_i=2, getfield_gc_r=2)
+ def test_heap_caching_quasi_immutable(self):
+ class A:
+ _immutable_fields_ = ['x?']
+ a1 = A()
+ a1.x = 5
+ a2 = A()
+ a2.x = 7
+
+ @jit.elidable
+ def get(n):
+ if n > 0:
+ return a1
+ return a2
+
+ def g(a):
+ return a.x
+
+ def fn(n):
+ jit.promote(n)
+ a = get(n)
+ return g(a) + a.x
+ res = self.interp_operations(fn, [7])
+ assert res == 10
+ self.check_operations_history(quasiimmut_field=1)
+
+
def test_heap_caching_multiple_tuples(self):
class Gbl(object):
pass
diff --git a/rpython/jit/metainterp/warmspot.py
b/rpython/jit/metainterp/warmspot.py
--- a/rpython/jit/metainterp/warmspot.py
+++ b/rpython/jit/metainterp/warmspot.py
@@ -529,7 +529,7 @@
def make_enter_function(self, jd):
from rpython.jit.metainterp.warmstate import WarmEnterState
state = WarmEnterState(self, jd)
- maybe_compile_and_run = state.make_entry_point()
+ maybe_compile_and_run, EnterJitAssembler = state.make_entry_point()
jd.warmstate = state
def crash_in_jit(e):
@@ -560,6 +560,7 @@
maybe_enter_jit._always_inline_ = True
jd._maybe_enter_jit_fn = maybe_enter_jit
jd._maybe_compile_and_run_fn = maybe_compile_and_run
+ jd._EnterJitAssembler = EnterJitAssembler
def make_driverhook_graphs(self):
s_Str = annmodel.SomeString()
@@ -842,12 +843,8 @@
# while 1:
# try:
# return portal(*args)
- # except ContinueRunningNormally, e:
- # *args = *e.new_args
- # except DoneWithThisFrame, e:
- # return e.return
- # except ExitFrameWithException, e:
- # raise Exception, e.value
+ # except JitException, e:
+ # return handle_jitexception(e)
#
# def portal(*args):
# while 1:
@@ -884,90 +881,79 @@
rtyper = self.translator.rtyper
RESULT = PORTALFUNC.RESULT
result_kind = history.getkind(RESULT)
+ assert result_kind.startswith(jd.result_type)
ts = self.cpu.ts
state = jd.warmstate
maybe_compile_and_run = jd._maybe_compile_and_run_fn
+ EnterJitAssembler = jd._EnterJitAssembler
def ll_portal_runner(*args):
- start = True
- while 1:
- try:
- # maybe enter from the function's start. Note that the
- # 'start' variable is constant-folded away because it's
- # the first statement in the loop.
- if start:
- maybe_compile_and_run(
- state.increment_function_threshold, *args)
- #
- # then run the normal portal function, i.e. the
- # interpreter's main loop. It might enter the jit
- # via maybe_enter_jit(), which typically ends with
- # handle_fail() being called, which raises on the
- # following exceptions --- catched here, because we
- # want to interrupt the whole interpreter loop.
- return support.maybe_on_top_of_llinterp(rtyper,
- portal_ptr)(*args)
- except jitexc.ContinueRunningNormally as e:
+ try:
+ # maybe enter from the function's start.
+ maybe_compile_and_run(
+ state.increment_function_threshold, *args)
+ #
+ # then run the normal portal function, i.e. the
+ # interpreter's main loop. It might enter the jit
+ # via maybe_enter_jit(), which typically ends with
+ # handle_fail() being called, which raises on the
+ # following exceptions --- catched here, because we
+ # want to interrupt the whole interpreter loop.
+ return support.maybe_on_top_of_llinterp(rtyper,
+ portal_ptr)(*args)
+ except jitexc.JitException as e:
+ result = handle_jitexception(e)
+ if result_kind != 'void':
+ result = specialize_value(RESULT, result)
+ return result
+
+ def handle_jitexception(e):
+ # XXX there are too many exceptions all around...
+ while True:
+ if isinstance(e, EnterJitAssembler):
+ try:
+ return e.execute()
+ except jitexc.JitException as e:
+ continue
+ #
+ if isinstance(e, jitexc.ContinueRunningNormally):
args = ()
for ARGTYPE, attrname, count in portalfunc_ARGS:
x = getattr(e, attrname)[count]
x = specialize_value(ARGTYPE, x)
args = args + (x,)
- start = False
- continue
- except jitexc.DoneWithThisFrameVoid:
- assert result_kind == 'void'
- return
- except jitexc.DoneWithThisFrameInt as e:
- assert result_kind == 'int'
- return specialize_value(RESULT, e.result)
- except jitexc.DoneWithThisFrameRef as e:
- assert result_kind == 'ref'
- return specialize_value(RESULT, e.result)
- except jitexc.DoneWithThisFrameFloat as e:
- assert result_kind == 'float'
- return specialize_value(RESULT, e.result)
- except jitexc.ExitFrameWithExceptionRef as e:
+ try:
+ result = support.maybe_on_top_of_llinterp(rtyper,
+ portal_ptr)(*args)
+ except jitexc.JitException as e:
+ continue
+ if result_kind != 'void':
+ result = unspecialize_value(result)
+ return result
+ #
+ if result_kind == 'void':
+ if isinstance(e, jitexc.DoneWithThisFrameVoid):
+ return None
+ if result_kind == 'int':
+ if isinstance(e, jitexc.DoneWithThisFrameInt):
+ return e.result
+ if result_kind == 'ref':
+ if isinstance(e, jitexc.DoneWithThisFrameRef):
+ return e.result
+ if result_kind == 'float':
+ if isinstance(e, jitexc.DoneWithThisFrameFloat):
+ return e.result
+ #
+ if isinstance(e, jitexc.ExitFrameWithExceptionRef):
value = ts.cast_to_baseclass(e.value)
if not we_are_translated():
raise LLException(ts.get_typeptr(value), value)
else:
value = cast_base_ptr_to_instance(Exception, value)
+ assert value is not None
raise value
-
- def handle_jitexception(e):
- # XXX the bulk of this function is mostly a copy-paste from above
- try:
- raise e
- except jitexc.ContinueRunningNormally as e:
- args = ()
- for ARGTYPE, attrname, count in portalfunc_ARGS:
- x = getattr(e, attrname)[count]
- x = specialize_value(ARGTYPE, x)
- args = args + (x,)
- result = ll_portal_runner(*args)
- if result_kind != 'void':
- result = unspecialize_value(result)
- return result
- except jitexc.DoneWithThisFrameVoid:
- assert result_kind == 'void'
- return
- except jitexc.DoneWithThisFrameInt as e:
- assert result_kind == 'int'
- return e.result
- except jitexc.DoneWithThisFrameRef as e:
- assert result_kind == 'ref'
- return e.result
- except jitexc.DoneWithThisFrameFloat as e:
- assert result_kind == 'float'
- return e.result
- except jitexc.ExitFrameWithExceptionRef as e:
- value = ts.cast_to_baseclass(e.value)
- if not we_are_translated():
- raise LLException(ts.get_typeptr(value), value)
- else:
- value = cast_base_ptr_to_instance(Exception, value)
- raise value
+ #
+ raise AssertionError("all cases should have been handled")
jd._ll_portal_runner = ll_portal_runner # for debugging
jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE,
diff --git a/rpython/jit/metainterp/warmstate.py
b/rpython/jit/metainterp/warmstate.py
--- a/rpython/jit/metainterp/warmstate.py
+++ b/rpython/jit/metainterp/warmstate.py
@@ -2,7 +2,7 @@
import weakref
from rpython.jit.codewriter import support, heaptracker, longlong
-from rpython.jit.metainterp import resoperation, history
+from rpython.jit.metainterp import resoperation, history, jitexc
from rpython.rlib.debug import debug_start, debug_stop, debug_print
from rpython.rlib.debug import have_debug_prints_for
from rpython.rlib.jit import PARAMETERS
@@ -348,8 +348,9 @@
def make_entry_point(self):
"NOT_RPYTHON"
- if hasattr(self, 'maybe_compile_and_run'):
- return self.maybe_compile_and_run
+ from rpython.jit.metainterp import compile
+ if hasattr(self, 'entry_point_fns'):
+ return self.entry_point_fns
warmrunnerdesc = self.warmrunnerdesc
metainterp_sd = warmrunnerdesc.metainterp_sd
@@ -362,6 +363,8 @@
confirm_enter_jit = self.confirm_enter_jit
range_red_args = unrolling_iterable(
range(num_green_args, num_green_args + jitdriver_sd.num_red_args))
+ name_red_args = unrolling_iterable(
+ [(i, 'arg%d' % i) for i in range(jitdriver_sd.num_red_args)])
# get a new specialized copy of the method
ARGS = []
for kind in jitdriver_sd.red_args_types:
@@ -376,6 +379,7 @@
func_execute_token = self.cpu.make_execute_token(*ARGS)
cpu = self.cpu
jitcounter = self.warmrunnerdesc.jitcounter
+ result_type = jitdriver_sd.result_type
def execute_assembler(loop_token, *args):
# Call the backend to run the 'looptoken' with the given
@@ -396,8 +400,23 @@
#
# Handle the failure
fail_descr = cpu.get_latest_descr(deadframe)
+ # First, a fast path to avoid raising and immediately catching
+ # a DoneWithThisFrame exception
+ if result_type == history.VOID:
+ if isinstance(fail_descr, compile.DoneWithThisFrameDescrVoid):
+ return None
+ if result_type == history.INT:
+ if isinstance(fail_descr, compile.DoneWithThisFrameDescrInt):
+ return fail_descr.get_result(cpu, deadframe)
+ if result_type == history.REF:
+ if isinstance(fail_descr, compile.DoneWithThisFrameDescrRef):
+ return fail_descr.get_result(cpu, deadframe)
+ if result_type == history.FLOAT:
+ if isinstance(fail_descr, compile.DoneWithThisFrameDescrFloat):
+ return fail_descr.get_result(cpu, deadframe)
+ #
+ # General case
fail_descr.handle_fail(deadframe, metainterp_sd, jitdriver_sd)
- #
assert 0, "should have raised"
def bound_reached(hash, cell, *args):
@@ -419,7 +438,8 @@
def maybe_compile_and_run(increment_threshold, *args):
"""Entry point to the JIT. Called at the point with the
- can_enter_jit() hint.
+ can_enter_jit() hint, and at the start of a function
+ with a different threshold.
"""
# Look for the cell corresponding to the current greenargs.
# Search for the JitCell that is of the correct subclass of
@@ -439,14 +459,6 @@
bound_reached(hash, None, *args)
return
- # Workaround for issue #2200, maybe temporary. This is not
- # a proper fix, but only a hack that should work well enough
- # for PyPy's main jitdriver... See test_issue2200_recursion
- from rpython.jit.metainterp.blackhole import workaround2200
- if workaround2200.active:
- workaround2200.active = False
- return
-
# Here, we have found 'cell'.
#
if cell.flags & (JC_TRACING | JC_TEMPORARY):
@@ -484,14 +496,27 @@
execute_args = ()
for i in range_red_args:
execute_args += (unspecialize_value(args[i]), )
- # run it! this executes until interrupted by an exception
- execute_assembler(procedure_token, *execute_args)
- assert 0, "should not reach this point"
+ # run it, but from outside in ll_portal_runner, not from here
+ # (this avoids RPython-level recursion with no corresponding
+ # app-level recursion, as shown by issues 2200 and 2335)
+ raise EnterJitAssembler(procedure_token, *execute_args)
+
+ class EnterJitAssembler(jitexc.JitException):
+ def __init__(self, procedure_token, *args):
+ self.procedure_token = procedure_token
+ for i, argname in name_red_args:
+ setattr(self, argname, args[i])
+ def execute(self):
+ args = ()
+ for i, argname in name_red_args:
+ args += (getattr(self, argname), )
+ return execute_assembler(self.procedure_token, *args)
maybe_compile_and_run._dont_inline_ = True
- self.maybe_compile_and_run = maybe_compile_and_run
self.execute_assembler = execute_assembler
- return maybe_compile_and_run
+ self.entry_point_fns = (maybe_compile_and_run,
+ EnterJitAssembler)
+ return self.entry_point_fns
# ----------
diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py
--- a/rpython/rlib/ropenssl.py
+++ b/rpython/rlib/ropenssl.py
@@ -593,11 +593,6 @@
HASH_MALLOC_SIZE = EVP_MD_SIZE + EVP_MD_CTX_SIZE \
+ rffi.sizeof(EVP_MD) * 2 + 208
-OBJ_NAME_CALLBACK = lltype.Ptr(lltype.FuncType(
- [OBJ_NAME, rffi.VOIDP], lltype.Void))
-OBJ_NAME_do_all = external(
- 'OBJ_NAME_do_all', [rffi.INT, OBJ_NAME_CALLBACK, rffi.VOIDP], lltype.Void)
-
def init_ssl():
libssl_SSL_load_error_strings()
libssl_SSL_library_init()
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -220,7 +220,7 @@
pass
if _WIN32:
- includes = ['io.h', 'sys/utime.h', 'sys/types.h']
+ includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h']
libraries = []
else:
if sys.platform.startswith(('darwin', 'netbsd', 'openbsd')):
@@ -704,10 +704,10 @@
c_execve = external('execve',
[rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP], rffi.INT,
save_err=rffi.RFFI_SAVE_ERRNO)
-c_spawnv = external('spawnv',
+c_spawnv = external(UNDERSCORE_ON_WIN32 + 'spawnv',
[rffi.INT, rffi.CCHARP, rffi.CCHARPP], rffi.INT,
save_err=rffi.RFFI_SAVE_ERRNO)
-c_spawnve = external('spawnve',
+c_spawnve = external(UNDERSCORE_ON_WIN32 + 'spawnve',
[rffi.INT, rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP],
rffi.INT,
save_err=rffi.RFFI_SAVE_ERRNO)
diff --git a/rpython/rlib/test/test_rsocket.py
b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -313,8 +313,10 @@
assert isinstance(lst, list)
found = False
for family, socktype, protocol, canonname, addr in lst:
- if addr.get_host() == '104.130.43.121':
+ if addr.get_host() in ('104.130.43.121', '23.253.135.79'):
found = True
+ elif family == AF_INET:
+ print 'pydotorg changed to', addr.get_host()
result[i] += found
def test_getaddrinfo_pydotorg():
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -171,10 +171,7 @@
_length_ = 2
@property
def value(self):
- if sys.byteorder == 'little':
- res = self[0] | (self[1] << 64)
- else:
- res = self[1] | (self[0] << 64)
+ res = self[0] | (self[1] << 64)
if res >= (1 << 127):
res -= 1 << 128
return res
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit