[pypy-commit] pypy new-jit-log: merge default

plan_rich pypy.commits at gmail.com
Thu Jul 21 09:18:15 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: new-jit-log
Changeset: r85790:3a2bd151550e
Date: 2016-07-21 14:59 +0200
http://bitbucket.org/pypy/pypy/changeset/3a2bd151550e/

Log:	merge default

diff --git a/pypy/doc/install.rst b/pypy/doc/install.rst
--- a/pypy/doc/install.rst
+++ b/pypy/doc/install.rst
@@ -39,17 +39,16 @@
 library.
 
 If you want to install 3rd party libraries, the most convenient way is
-to install pip_ (unless you want to install virtualenv as explained
-below; then you can directly use pip inside virtualenvs):
+to install pip_ using ensurepip_ (unless you want to install virtualenv as 
+explained below; then you can directly use pip inside virtualenvs):
 
 .. code-block:: console
 
-    $ curl -O https://bootstrap.pypa.io/get-pip.py
-    $ ./pypy-2.1/bin/pypy get-pip.py
-    $ ./pypy-2.1/bin/pip install pygments  # for example
+    $ ./pypy-xxx/bin/pypy -m ensurepip
+    $ ./pypy-xxx/bin/pip install pygments  # for example
 
-Third party libraries will be installed in ``pypy-2.1/site-packages``, and
-the scripts in ``pypy-2.1/bin``.
+Third party libraries will be installed in ``pypy-xxx/site-packages``, and
+the scripts in ``pypy-xxx/bin``.
 
 
 Installing using virtualenv
@@ -61,7 +60,7 @@
 checkout::
 
 	# from a tarball
-	$ virtualenv -p /opt/pypy-c-jit-41718-3fb486695f20-linux/bin/pypy my-pypy-env
+	$ virtualenv -p /opt/pypy-xxx/bin/pypy my-pypy-env
 
 	# from the mercurial checkout
 	$ virtualenv -p /path/to/pypy/pypy/translator/goal/pypy-c my-pypy-env
@@ -69,7 +68,7 @@
 Note that bin/python is now a symlink to bin/pypy.
 
 .. _pip: http://pypi.python.org/pypi/pip
-
+.. _ensurepip: https://docs.python.org/2.7/library/ensurepip.html
 
 Building PyPy yourself
 ~~~~~~~~~~~~~~~~~~~~~~
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
@@ -424,6 +424,7 @@
         --TICK--
         i123 = arraylen_gc(p67, descr=<ArrayP .>)
         i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, descr=<Calli . i EF=5 OS=110>)
+        check_memory_error(i119)
         raw_store(i119, 0, i160, descr=<ArrayS 2>)
         raw_store(i119, 2, i160, descr=<ArrayS 2>)
         raw_store(i119, 4, i160, descr=<ArrayS 2>)
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -82,9 +82,6 @@
         self.failure_recovery_code = [0, 0, 0, 0]
 
     def _build_propagate_exception_path(self):
-        if not self.cpu.propagate_exception_descr:
-            return      # not supported (for tests, or non-translated)
-        #
         mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         self._store_and_reset_exception(mc, r.r0)
         ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
@@ -372,9 +369,9 @@
             self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False,
                                          is_frame=True)
 
-    def propagate_memoryerror_if_r0_is_null(self):
-        # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null
-        self.mc.CMP_ri(r.r0.value, 0)
+    def propagate_memoryerror_if_reg_is_null(self, reg_loc):
+        # see ../x86/assembler.py:genop_discard_check_memory_error()
+        self.mc.CMP_ri(reg_loc.value, 0)
         self.mc.B(self.propagate_exception_path, c=c.EQ)
 
     def _push_all_regs_to_jitframe(self, mc, ignored_regs, withfloats,
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -1050,9 +1050,8 @@
         regalloc = self._regalloc
         return regalloc.operations[regalloc.rm.position + delta]
 
-    def emit_op_call_malloc_gc(self, op, arglocs, regalloc, fcond):
-        self._emit_call(op, arglocs, fcond=fcond)
-        self.propagate_memoryerror_if_r0_is_null()
+    def emit_op_check_memory_error(self, op, arglocs, regalloc, fcond):
+        self.propagate_memoryerror_if_reg_is_null(arglocs[0])
         self._alignment_check()
         return fcond
 
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -594,8 +594,9 @@
         resloc = self.after_call(op)
         return resloc
 
-    def prepare_op_call_malloc_gc(self, op, fcond):
-        return self._prepare_call(op)
+    def prepare_op_check_memory_error(self, op, fcond):
+        argloc = self.make_sure_var_in_reg(op.getarg(0))
+        return [argloc]
 
     def _prepare_llong_binop_xx(self, op, fcond):
         # arg 0 is the address of the function
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
@@ -1521,6 +1521,11 @@
             lle = None
         self.last_exception = lle
 
+    def execute_check_memory_error(self, descr, value):
+        if not value:
+            from rpython.jit.backend.llsupport import llmodel
+            raise llmodel.MissingLatestDescrError
+
 
 def _getdescr(op):
     d = op.getdescr()
diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -48,7 +48,10 @@
         anything, it must be an optional MemoryError.
         """
         FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-        descr = get_call_descr(self, ARGS, RESULT)
+        # Note: the call may invoke the GC, which may run finalizers.
+        # Finalizers are constrained in what they can do, but we can't
+        # really express that in a useful way here.
+        descr = get_call_descr(self, ARGS, RESULT, EffectInfo.MOST_GENERAL)
         setattr(self, funcname, func)
         setattr(self, funcname + '_FUNCPTR', FUNCPTR)
         setattr(self, funcname + '_descr', descr)
diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -408,6 +408,9 @@
         deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
         descr = deadframe.jf_descr
         res = history.AbstractDescr.show(self, descr)
+        if not we_are_translated():   # tests only: for missing
+            if res is None:           # propagate_exception_descr
+                raise MissingLatestDescrError
         assert isinstance(res, history.AbstractFailDescr)
         return res
 
@@ -816,6 +819,9 @@
         calldescr.call_stub_i(func, args_i, args_r, args_f)
 
 
+class MissingLatestDescrError(Exception):
+    """For propagate_exception_descr in untranslated tests."""
+
 final_descr_rd_locs = [rffi.cast(rffi.USHORT, 0)]
 history.BasicFinalDescr.rd_locs = final_descr_rd_locs
 compile._DoneWithThisFrameDescr.rd_locs = final_descr_rd_locs
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -26,7 +26,8 @@
 class GcRewriterAssembler(object):
     """ This class performs the following rewrites on the list of operations:
 
-     - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY
+     - Turn all NEW_xxx to either a CALL_R/CHECK_MEMORY_ERROR,
+       or a CALL_MALLOC_NURSERY,
        followed by SETFIELDs in order to initialize their GC fields.  The
        two advantages of CALL_MALLOC_NURSERY is that it inlines the common
        path, and we need only one such operation to allocate several blocks
@@ -715,16 +716,17 @@
         self._delayed_zero_setfields.clear()
 
     def _gen_call_malloc_gc(self, args, v_result, descr):
-        """Generate a CALL_MALLOC_GC with the given args."""
+        """Generate a CALL_R/CHECK_MEMORY_ERROR with the given args."""
         self.emitting_an_operation_that_can_collect()
-        op = ResOperation(rop.CALL_MALLOC_GC, args, descr=descr)
+        op = ResOperation(rop.CALL_R, args, descr=descr)
         self.replace_op_with(v_result, op)
         self.emit_op(op)
+        self.emit_op(ResOperation(rop.CHECK_MEMORY_ERROR, [op]))
         # In general, don't add v_result to write_barrier_applied:
         # v_result might be a large young array.
 
     def gen_malloc_fixedsize(self, size, typeid, v_result):
-        """Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, ...).
+        """Generate a CALL_R(malloc_fixedsize_fn, ...).
         Used on Boehm, and on the framework GC for large fixed-size
         mallocs.  (For all I know this latter case never occurs in
         practice, but better safe than sorry.)
@@ -744,7 +746,7 @@
         self.remember_write_barrier(v_result)
 
     def gen_boehm_malloc_array(self, arraydescr, v_num_elem, v_result):
-        """Generate a CALL_MALLOC_GC(malloc_array_fn, ...) for Boehm."""
+        """Generate a CALL_R(malloc_array_fn, ...) for Boehm."""
         addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_array')
         self._gen_call_malloc_gc([ConstInt(addr),
                                   ConstInt(arraydescr.basesize),
@@ -755,7 +757,7 @@
                                  self.gc_ll_descr.malloc_array_descr)
 
     def gen_malloc_array(self, arraydescr, v_num_elem, v_result):
-        """Generate a CALL_MALLOC_GC(malloc_array_fn, ...) going either
+        """Generate a CALL_R(malloc_array_fn, ...) going either
         to the standard or the nonstandard version of the function."""
         #
         if (arraydescr.basesize == self.gc_ll_descr.standard_array_basesize
@@ -782,13 +784,13 @@
         self._gen_call_malloc_gc(args, v_result, calldescr)
 
     def gen_malloc_str(self, v_num_elem, v_result):
-        """Generate a CALL_MALLOC_GC(malloc_str_fn, ...)."""
+        """Generate a CALL_R(malloc_str_fn, ...)."""
         addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_str')
         self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result,
                                  self.gc_ll_descr.malloc_str_descr)
 
     def gen_malloc_unicode(self, v_num_elem, v_result):
-        """Generate a CALL_MALLOC_GC(malloc_unicode_fn, ...)."""
+        """Generate a CALL_R(malloc_unicode_fn, ...)."""
         addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_unicode')
         self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result,
                                  self.gc_ll_descr.malloc_unicode_descr)
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -254,8 +254,9 @@
             jump()
         """, """
             [p1]
-            p0 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
-                                descr=malloc_fixedsize_descr)
+            p0 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
+                        descr=malloc_fixedsize_descr)
+            check_memory_error(p0)
             jump()
         """)
 
@@ -267,10 +268,12 @@
             jump()
         """, """
             []
-            p0 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
-                                descr=malloc_fixedsize_descr)
-            p1 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
-                                descr=malloc_fixedsize_descr)
+            p0 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
+                        descr=malloc_fixedsize_descr)
+            check_memory_error(p0)
+            p1 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
+                        descr=malloc_fixedsize_descr)
+            check_memory_error(p1)
             jump()
         """)
 
@@ -281,16 +284,17 @@
             jump()
         """, """
             []
-            p0 = call_malloc_gc(ConstClass(malloc_array),   \
+            p0 = call_r(ConstClass(malloc_array),           \
                                 %(adescr.basesize)d,        \
                                 10,                         \
                                 %(adescr.itemsize)d,        \
                                 %(adescr.lendescr.offset)d, \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 ##      should ideally be:
-##            p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
+##            p0 = call_r(ConstClass(malloc_fixedsize), \
 ##                                %(adescr.basesize + 10 * adescr.itemsize)d, \
 ##                                descr=malloc_fixedsize_descr)
 ##            setfield_gc(p0, 10, descr=alendescr)
@@ -302,12 +306,13 @@
             jump()
         """, """
             [i1]
-            p0 = call_malloc_gc(ConstClass(malloc_array),   \
+            p0 = call_r(ConstClass(malloc_array),   \
                                 %(adescr.basesize)d,        \
                                 i1,                         \
                                 %(adescr.itemsize)d,        \
                                 %(adescr.lendescr.offset)d, \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 
@@ -318,8 +323,9 @@
             jump()
         """, """
             [p1]
-            p0 = call_malloc_gc(ConstClass(malloc_fixedsize), 102, \
+            p0 = call_r(ConstClass(malloc_fixedsize), 102, \
                                 descr=malloc_fixedsize_descr)
+            check_memory_error(p0)
             gc_store(p0, 0, ConstClass(o_vtable), %(vtable_descr.field_size)s)
             jump()
         """)
@@ -331,12 +337,13 @@
             jump()
         """, """
             [i1]
-            p0 = call_malloc_gc(ConstClass(malloc_array), \
+            p0 = call_r(ConstClass(malloc_array),         \
                                 %(strdescr.basesize)d,    \
                                 i1,                       \
                                 %(strdescr.itemsize)d,    \
                                 %(strlendescr.offset)d,   \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 
@@ -347,16 +354,17 @@
             jump()
         """, """
             [i1]
-            p0 = call_malloc_gc(ConstClass(malloc_array),   \
+            p0 = call_r(ConstClass(malloc_array),           \
                                 %(unicodedescr.basesize)d,  \
                                 10,                         \
                                 %(unicodedescr.itemsize)d,  \
                                 %(unicodelendescr.offset)d, \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 ##      should ideally be:
-##            p0 = call_malloc_gc(ConstClass(malloc_fixedsize),   \
+##            p0 = call_r(ConstClass(malloc_fixedsize),           \
 ##                                %(unicodedescr.basesize +       \
 ##                                  10 * unicodedescr.itemsize)d, \
 ##                                descr=malloc_fixedsize_descr)
@@ -545,11 +553,12 @@
             jump(i0)
         """, """
             [i0, p1]
-            p0 = call_malloc_gc(ConstClass(malloc_array_nonstandard), \
+            p0 = call_r(ConstClass(malloc_array_nonstandard),         \
                                 64, 8,                                \
                                 %(nonstd_descr.lendescr.offset)d,     \
                                 6464, i0,                             \
                                 descr=malloc_array_nonstandard_descr)
+            check_memory_error(p0)
             cond_call_gc_wb_array(p0, i0, descr=wbdescr)
             gc_store_indexed(p0, i0, p1, 8, 64, 8)
             jump(i0)
@@ -563,9 +572,10 @@
             jump()
         """, """
             []
-            p0 = call_malloc_gc(ConstClass(malloc_array), 1,  \
+            p0 = call_r(ConstClass(malloc_array), 1,          \
                                 %(bdescr.tid)d, 103,          \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 
@@ -601,9 +611,10 @@
             jump()
         """, """
             []
-            p0 = call_malloc_gc(ConstClass(malloc_array), 1, \
+            p0 = call_r(ConstClass(malloc_array), 1,         \
                                 %(bdescr.tid)d, 20000000,    \
                                 descr=malloc_array_descr)
+            check_memory_error(p0)
             jump()
         """)
 
@@ -628,8 +639,9 @@
             jump()
         """, """
             [p1]
-            p0 = call_malloc_gc(ConstClass(malloc_big_fixedsize), 104, 9315, \
+            p0 = call_r(ConstClass(malloc_big_fixedsize), 104, 9315, \
                                 descr=malloc_big_fixedsize_descr)
+            check_memory_error(p0)
             gc_store(p0, 0,  0, %(vtable_descr.field_size)s)
             jump()
         """)
diff --git a/rpython/jit/backend/ppc/opassembler.py b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -1025,9 +1025,8 @@
 
     _mixin_ = True
 
-    def emit_call_malloc_gc(self, op, arglocs, regalloc):
-        self._emit_call(op, arglocs)
-        self.propagate_memoryerror_if_r3_is_null()
+    def emit_check_memory_error(self, op, arglocs, regalloc):
+        self.propagate_memoryerror_if_reg_is_null(arglocs[0])
 
     def emit_call_malloc_nursery(self, op, arglocs, regalloc):
         # registers r.RES and r.RSZ are allocated for this call
diff --git a/rpython/jit/backend/ppc/ppc_assembler.py b/rpython/jit/backend/ppc/ppc_assembler.py
--- a/rpython/jit/backend/ppc/ppc_assembler.py
+++ b/rpython/jit/backend/ppc/ppc_assembler.py
@@ -412,7 +412,7 @@
         # Check that we don't get NULL; if we do, we always interrupt the
         # current loop, as a "good enough" approximation (same as
         # emit_call_malloc_gc()).
-        self.propagate_memoryerror_if_r3_is_null()
+        self.propagate_memoryerror_if_reg_is_null(r.r3)
 
         mc.mtlr(r.RCS1.value)     # restore LR
         self._pop_core_regs_from_jitframe(mc, saved_regs)
@@ -594,9 +594,6 @@
             self.wb_slowpath[withcards + 2 * withfloats] = rawstart
 
     def _build_propagate_exception_path(self):
-        if not self.cpu.propagate_exception_descr:
-            return
-
         self.mc = PPCBuilder()
         #
         # read and reset the current exception
@@ -1326,11 +1323,8 @@
         pmc.b(offset)    # jump always
         pmc.overwrite()
 
-    def propagate_memoryerror_if_r3_is_null(self):
-        # if self.propagate_exception_path == 0 (tests), this may jump to 0
-        # and segfaults.  too bad.  the alternative is to continue anyway
-        # with r3==0, but that will segfault too.
-        self.mc.cmp_op(0, r.r3.value, 0, imm=True)
+    def propagate_memoryerror_if_reg_is_null(self, reg_loc):
+        self.mc.cmp_op(0, reg_loc.value, 0, imm=True)
         self.mc.b_cond_abs(self.propagate_exception_path, c.EQ)
 
     def write_new_force_index(self):
diff --git a/rpython/jit/backend/ppc/regalloc.py b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -533,8 +533,9 @@
         res = self.rm.force_allocate_reg(op)
         return [res]
 
-    def prepare_call_malloc_gc(self, op):
-        return self._prepare_call(op)
+    def prepare_check_memory_error(self, op):
+        loc = self.ensure_reg(op.getarg(0))
+        return [loc]
 
     def _prepare_guard(self, op, args=None):
         if args is None:
diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -22,6 +22,7 @@
 from rpython.jit.backend.detect_cpu import autodetect
 from rpython.jit.backend.llsupport import jitframe
 from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
+from rpython.jit.backend.llsupport.llmodel import MissingLatestDescrError
 from rpython.jit.backend.llsupport.rewrite import GcRewriterAssembler
 
 
@@ -4391,6 +4392,12 @@
                          'float', descr=calldescr)
             assert longlong.getrealfloat(res) == expected
 
+    def test_check_memory_error(self):
+        self.execute_operation(
+                       rop.CHECK_MEMORY_ERROR, [InputArgInt(12345)], 'void')
+        py.test.raises(MissingLatestDescrError, self.execute_operation,
+                       rop.CHECK_MEMORY_ERROR, [InputArgInt(0)], 'void')
+
     def test_compile_loop_with_target(self):
         looptoken = JitCellToken()
         targettoken1 = TargetToken()
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -292,9 +292,6 @@
         return rawstart
 
     def _build_propagate_exception_path(self):
-        if not self.cpu.propagate_exception_descr:
-            return      # not supported (for tests, or non-translated)
-        #
         self.mc = codebuf.MachineCodeBlockWrapper()
         self.mc.force_frame_size(DEFAULT_FRAME_BYTES)
         #
@@ -1532,15 +1529,9 @@
 
     # ----------
 
-    def genop_call_malloc_gc(self, op, arglocs, result_loc):
-        self._genop_call(op, arglocs, result_loc)
-        self.propagate_memoryerror_if_eax_is_null()
-
-    def propagate_memoryerror_if_eax_is_null(self):
-        # if self.propagate_exception_path == 0 (tests), this may jump to 0
-        # and segfaults.  too bad.  the alternative is to continue anyway
-        # with eax==0, but that will segfault too.
-        self.mc.TEST_rr(eax.value, eax.value)
+    def genop_discard_check_memory_error(self, op, arglocs):
+        reg = arglocs[0]
+        self.mc.TEST(reg, reg)
         if WORD == 4:
             self.mc.J_il(rx86.Conditions['Z'], self.propagate_exception_path)
             self.mc.add_pending_relocation()
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -902,9 +902,10 @@
     consider_call_release_gil_i = _consider_call_release_gil
     consider_call_release_gil_f = _consider_call_release_gil
     consider_call_release_gil_n = _consider_call_release_gil
-    
-    def consider_call_malloc_gc(self, op):
-        self._consider_call(op)
+
+    def consider_check_memory_error(self, op):
+        x = self.rm.make_sure_var_in_reg(op.getarg(0))
+        self.perform_discard(op, [x])
 
     def _consider_call_assembler(self, op):
         locs = self.locs_for_call_assembler(op)
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
@@ -356,9 +356,6 @@
         self.mc = None
 
     def _build_propagate_exception_path(self):
-        if not self.cpu.propagate_exception_descr:
-            return
-
         self.mc = InstrBuilder()
         #
         # read and reset the current exception
@@ -487,7 +484,7 @@
         # Check that we don't get NULL; if we do, we always interrupt the
         # current loop, as a "good enough" approximation (same as
         # emit_call_malloc_gc()).
-        self.propagate_memoryerror_if_r2_is_null(True)
+        self.propagate_memoryerror_if_reg_is_null(r.r2, True)
 
         self._pop_core_regs_from_jitframe(mc, saved_regs)
         self._pop_fp_regs_from_jitframe(mc)
@@ -797,12 +794,12 @@
             self.mc.BRC(condition, l.imm(off)) # branch over XGR
             self.mc.XGR(result_loc, result_loc)
 
-    def propagate_memoryerror_if_r2_is_null(self, pop_one_stackframe=False):
+    def propagate_memoryerror_if_reg_is_null(self, reg, pop_one_stackframe=False):
         # if self.propagate_exception_path == 0 (tests), this may jump to 0
         # and segfaults.  too bad.  the alternative is to continue anyway
-        # with r2==0, but that will segfault too.
+        # with reg==0, but that will segfault too.
         jmp_pos = self.mc.get_relative_pos()
-        # bails to propagate exception path if r2 != 0
+        # bails to propagate exception path if reg != 0
         self.mc.reserve_cond_jump()
 
         self.mc.load_imm(r.RETURN, self.propagate_exception_path)
@@ -812,7 +809,7 @@
 
         curpos = self.mc.currpos()
         pmc = OverwritingBuilder(self.mc, jmp_pos, 1)
-        pmc.CGIJ(r.r2, l.imm(0), c.NE, l.imm(curpos - jmp_pos))
+        pmc.CGIJ(reg, l.imm(0), c.NE, l.imm(curpos - jmp_pos))
         pmc.overwrite()
 
     def regalloc_push(self, loc, already_pushed):
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
@@ -421,9 +421,8 @@
 class AllocOpAssembler(object):
     _mixin_ = True
 
-    def emit_call_malloc_gc(self, op, arglocs, regalloc):
-        self._emit_call(op, arglocs)
-        self.propagate_memoryerror_if_r2_is_null()
+    def emit_check_memory_error(self, op, arglocs, regalloc):
+        self.propagate_memoryerror_if_reg_is_null(arglocs[0])
 
     def emit_call_malloc_nursery(self, op, arglocs, regalloc):
         # registers r.RES and r.RSZ are allocated for this call
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -828,8 +828,9 @@
     prepare_call_f = _prepare_call
     prepare_call_n = _prepare_call
 
-    def prepare_call_malloc_gc(self, op):
-        return self._prepare_call_default(op)
+    def prepare_check_memory_error(self, op):
+        loc = self.ensure_reg(op.getarg(0))
+        return [loc]
 
     def prepare_call_malloc_nursery(self, op):
         self.rm.force_allocate_reg(op, selected_reg=r.RES)
diff --git a/rpython/jit/backend/zarch/test/test_pool.py b/rpython/jit/backend/zarch/test/test_pool.py
--- a/rpython/jit/backend/zarch/test/test_pool.py
+++ b/rpython/jit/backend/zarch/test/test_pool.py
@@ -40,7 +40,7 @@
 
     def test_constant_in_call_malloc(self):
         c = ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234))
-        self.ensure_can_hold(rop.CALL_MALLOC_GC, [c], descr=self.calldescr)
+        self.ensure_can_hold(rop.COND_CALL, [c], descr=self.calldescr)
         assert self.const_in_pool(c)
         assert self.const_in_pool(ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234)))
 
diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py
--- a/rpython/jit/metainterp/executor.py
+++ b/rpython/jit/metainterp/executor.py
@@ -379,7 +379,7 @@
                          rop.CALL_RELEASE_GIL_F,
                          rop.CALL_RELEASE_GIL_N,
                          rop.QUASIIMMUT_FIELD,
-                         rop.CALL_MALLOC_GC,
+                         rop.CHECK_MEMORY_ERROR,
                          rop.CALL_MALLOC_NURSERY,
                          rop.CALL_MALLOC_NURSERY_VARSIZE,
                          rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME,
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -345,7 +345,8 @@
             opnum == rop.ENTER_PORTAL_FRAME or   # no effect whatsoever
             opnum == rop.LEAVE_PORTAL_FRAME or   # no effect whatsoever
             opnum == rop.COPYSTRCONTENT or       # no effect on GC struct/array
-            opnum == rop.COPYUNICODECONTENT):    # no effect on GC struct/array
+            opnum == rop.COPYUNICODECONTENT or   # no effect on GC struct/array
+            opnum == rop.CHECK_MEMORY_ERROR):    # may only abort the whole loop
             return
         if rop.is_call(op.opnum):
             if rop.is_call_assembler(op.getopnum()):
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -400,6 +400,12 @@
 
     def _force_elements(self, op, optforce, descr):
         self.size = -1
+        # at this point we have just written the
+        # 'op = CALL_I(..., OS_RAW_MALLOC_VARSIZE_CHAR)'.
+        # Emit now a CHECK_MEMORY_ERROR resop.
+        check_op = ResOperation(rop.CHECK_MEMORY_ERROR, [op])
+        optforce.emit_operation(check_op)
+        #
         buffer = self._get_buffer()
         for i in range(len(buffer.offsets)):
             # write the value
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -1818,7 +1818,7 @@
         [i1]
         label(i1)
         i2 = call_i('malloc', 20, descr=raw_malloc_descr)
-        #guard_no_exception() []  # XXX should appear
+        check_memory_error(i2)
         raw_store(i2, 0, i1, descr=rawarraydescr_char)
         raw_store(i2, 1, 123, descr=rawarraydescr_char)
         raw_store(i2, 2, 456, descr=rawarraydescr_char)
@@ -1844,7 +1844,7 @@
         [i1]
         label(i1)
         i2 = call_i('malloc', 10, descr=raw_malloc_descr)
-        #guard_no_exception() []  # XXX should appear
+        check_memory_error(i2)
         raw_store(i2, 0, i1, descr=rawarraydescr)
         setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
         call_n('free', i2, descr=raw_free_descr)
@@ -1867,7 +1867,7 @@
         [i1]
         label(i1)
         i2 = call_i('malloc', 10, descr=raw_malloc_descr)
-        #guard_no_exception() []  # XXX should appear
+        check_memory_error(i2)
         raw_store(i2, 0, i1, descr=rawarraydescr)
         i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char)
         call_n('free', i2, descr=raw_free_descr)
@@ -1930,7 +1930,7 @@
         label(i0, i1)
         # these ops are generated by VirtualRawBufferValue._really_force
         i2 = call_i('malloc', 10, descr=raw_malloc_descr)
-        #guard_no_exception() []  # XXX should appear
+        check_memory_error(i2)
         raw_store(i2, 0, 42, descr=rawarraydescr_char)
         raw_store(i2, 5, 4242, descr=rawarraydescr_char)
         # this is generated by VirtualRawSliceValue._really_force
@@ -1959,7 +1959,7 @@
         call_n('free', i0, descr=raw_free_descr)
         label(i2)
         i3 = call_i('malloc', 10, descr=raw_malloc_descr)
-        #guard_no_exception() []  # XXX should appear
+        check_memory_error(i3)
         raw_store(i3, 0, i2, descr=rawarraydescr)
         jump(i3)
         """
@@ -2032,6 +2032,7 @@
         expected = """
         [f1]
         i0 = call_i('malloc', 16, descr=raw_malloc_descr)
+        check_memory_error(i0)
         escape_n(i0)
         i1 = int_add(i0, 8)
         setarrayitem_raw(i1, 0, f1, descr=rawarraydescr_float)
@@ -8802,14 +8803,22 @@
         ops = """
         [i1]
         i0 = call_i(123, 10, descr=raw_malloc_descr)
+        guard_no_exception() []
         jump(i0)
         """
-        self.optimize_loop(ops, ops)
+        expected = """
+        [i1]
+        i0 = call_i(123, 10, descr=raw_malloc_descr)
+        check_memory_error(i0)
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
 
     def test_raw_buffer_int_is_true(self):
         ops = """
         [iinp]
         i0 = call_i(123, 10, descr=raw_malloc_descr)
+        guard_no_exception() []
         i1 = int_is_true(i0)
         guard_true(i1) []
         i2 = int_is_zero(i0)
@@ -8819,6 +8828,7 @@
         expected = """
         [i2]
         i0 = call_i(123, 10, descr=raw_malloc_descr)
+        check_memory_error(i0)
         jump(i0)
         """
         self.optimize_loop(ops, expected)
@@ -8877,6 +8887,7 @@
         ops = """
         [i0]
         i = call_i('malloc', 10, descr=raw_malloc_descr)
+        guard_no_exception() []
         is = int_add(i, 8)
         escape_n(i)
         i1 = int_add(i0, 1)
@@ -8888,6 +8899,7 @@
         expected = """
         [i0]
         i = call_i('malloc', 10, descr=raw_malloc_descr)
+        check_memory_error(i)
         escape_n(i)
         i1 = int_add(i0, 1)
         i2 = int_lt(i1, 100)
@@ -8955,6 +8967,7 @@
         ops = """
         [i0, p0]
         i2 = call_i('malloc', 10, descr=raw_malloc_descr)
+        guard_no_exception() []
         setarrayitem_raw(i2, 0, 13, descr=rawarraydescr)
         setfield_gc(p0, i2, descr=valuedescr)
         i1 = int_add(i0, 1)
@@ -8976,12 +8989,20 @@
         ops = """
         []
         i2 = call_i('malloc', 10, descr=raw_malloc_descr)
+        guard_no_exception() []
         guard_value(i2, 12345) []
         jump()
         """
+        expected = """
+        []
+        i2 = call_i('malloc', 10, descr=raw_malloc_descr)
+        check_memory_error(i2)
+        guard_value(i2, 12345) []
+        jump()
+        """
         # getting InvalidLoop would be a good idea, too.
         # (this test was written to show it would previously crash)
-        self.optimize_loop(ops, ops)
+        self.optimize_loop(ops, expected)
 
     def test_unroll_constant_null_1(self):
         ops = """
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -1157,7 +1157,7 @@
     'CALL_RELEASE_GIL/*d/fin',
     # release the GIL and "close the stack" for asmgcc
     'CALL_PURE/*d/rfin',             # removed before it's passed to the backend
-    'CALL_MALLOC_GC/*d/r',      # like CALL, but NULL => propagate MemoryError
+    'CHECK_MEMORY_ERROR/1/n',   # after a CALL: NULL => propagate MemoryError
     'CALL_MALLOC_NURSERY/1/r',  # nursery malloc, const number of bytes, zeroed
     'CALL_MALLOC_NURSERY_VARSIZE/3d/r',
     'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1/r',
diff --git a/rpython/rlib/rvmprof/src/vmprof_config.h b/rpython/rlib/rvmprof/src/vmprof_config.h
--- a/rpython/rlib/rvmprof/src/vmprof_config.h
+++ b/rpython/rlib/rvmprof/src/vmprof_config.h
@@ -4,7 +4,7 @@
 #  define HAVE_SIGNAL_H
 #endif
 
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
   #ifdef __i386__
     #define PC_FROM_UCONTEXT uc_mcontext.mc_eip
   #else


More information about the pypy-commit mailing list