Commits

Maciej Fijalkowski committed a4cc624 Merge

merge

Comments (0)

Files changed (24)

     DEALINGS IN THE SOFTWARE.
 
 
-PyPy Copyright holders 2003-2012
+PyPy Copyright holders 2003-2013
 ----------------------------------- 
 
 Except when otherwise stated (look for LICENSE files or information at

lib-python/2.7/sre_parse.py

 
 from sre_constants import *
 
+try:
+    from __pypy__ import newdict
+except ImportError:
+    def newdict(tp):
+        return {}
+
 SPECIAL_CHARS = ".\\[{()*+?^$|"
 REPEAT_CHARS = "*+?{"
 
         self.flags = 0
         self.open = []
         self.groups = 1
-        self.groupdict = {}
+        self.groupdict = newdict("module")
     def opengroup(self, name=None):
         gid = self.groups
         self.groups = gid + 1

pypy/doc/index.rst

 .. _Python: http://docs.python.org/index.html
 .. _`more...`: architecture.html#mission-statement 
 .. _`PyPy blog`: http://morepypy.blogspot.com/
-.. _`development bug/feature tracker`: https://codespeak.net/issue/pypy-dev/ 
+.. _`development bug/feature tracker`: https://bugs.pypy.org
 .. _here: http://tismerysoft.de/pypy/irc-logs/pypy
 .. _`Mercurial commit mailing list`: http://python.org/mailman/listinfo/pypy-commit
 .. _`development mailing list`: http://python.org/mailman/listinfo/pypy-dev

pypy/jit/backend/arm/assembler.py

 from __future__ import with_statement
 import os
+from pypy.jit.backend.llsupport import jitframe
 from pypy.jit.backend.arm.helper.assembler import saved_registers
 from pypy.jit.backend.arm import conditions as c
 from pypy.jit.backend.arm import registers as r
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.jit.backend.arm.opassembler import ResOpAssembler
 from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
-                             have_debug_prints)
+                             have_debug_prints, fatalerror)
 from pypy.rlib.jit import AsmInfo
 from pypy.rlib.objectmodel import compute_unique_id
 
 # XXX Move to llsupport
-from pypy.jit.backend.x86.support import values_array, memcpy_fn
+from pypy.jit.backend.x86.support import memcpy_fn
 
 DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
                               ('type', lltype.Char),  # 'b'ridge, 'l'abel or
 
     debug = True
 
-    def __init__(self, cpu, failargs_limit=1000):
+    def __init__(self, cpu, translate_support_code=False):
         self.cpu = cpu
-        self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
-        self.fail_boxes_float = values_array(longlong.FLOATSTORAGE,
-                                                            failargs_limit)
-        self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit)
-        self.fail_boxes_count = 0
-        self.fail_force_index = 0
         self.setup_failure_recovery()
         self.mc = None
         self.memcpy_addr = 0
         self._debug = False
         self.loop_run_counters = []
         self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
+        self.force_token_to_dead_frame = {}    # XXX temporary hack
 
     def set_debug(self, v):
         r = self._debug
         gc_ll_descr.initialize()
         self._build_wb_slowpath(False)
         self._build_wb_slowpath(True)
+        self._build_failure_recovery(exc=True, withfloats=False)
+        self._build_failure_recovery(exc=False, withfloats=False)
         if self.cpu.supports_floats:
             self._build_wb_slowpath(False, withfloats=True)
             self._build_wb_slowpath(True, withfloats=True)
+            self._build_failure_recovery(exc=True, withfloats=True)
+            self._build_failure_recovery(exc=False, withfloats=True)
         self._build_propagate_exception_path()
         if gc_ll_descr.get_malloc_slowpath_addr is not None:
             self._build_malloc_slowpath()
         if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
             self._build_release_gil(gc_ll_descr.gcrootmap)
         self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
-        self._exit_code_addr = self._gen_exit_path()
-        self._leave_jitted_hook_save_exc = \
-                                    self._gen_leave_jitted_hook_code(True)
-        self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
+
         if not self._debug:
             # if self._debug is already set it means that someone called
             # set_debug by hand before initializing the assembler. Leave it
         self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func)
         self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
 
-    def _gen_leave_jitted_hook_code(self, save_exc):
-        mc = ARMv7Builder()
-        if self.cpu.supports_floats:
-            floats = r.caller_vfp_resp
-        else:
-            floats = []
-        with saved_registers(mc, r.caller_resp + [r.lr], floats):
-            addr = self.cpu.get_on_leave_jitted_int(save_exception=save_exc)
-            mc.BL(addr)
-        assert self._exit_code_addr != 0
-        mc.B(self._exit_code_addr)
-        return mc.materialize(self.cpu.asmmemmgr, [],
-                               self.cpu.gc_ll_descr.gcrootmap)
-
     def _build_propagate_exception_path(self):
         if self.cpu.propagate_exception_v < 0:
             return      # not supported (for tests, or non-translated)
         #
         mc = ARMv7Builder()
-        # call on_leave_jitted_save_exc()
-        if self.cpu.supports_floats:
-            floats = r.caller_vfp_resp
-        else:
-            floats = []
-        with saved_registers(mc, r.caller_resp + [r.lr], floats):
-            addr = self.cpu.get_on_leave_jitted_int(save_exception=True,
-                                                default_to_memoryerror=True)
-            mc.BL(addr)
-        mc.gen_load_int(r.ip.value, self.cpu.propagate_exception_v)
-        mc.MOV_rr(r.r0.value, r.ip.value)
+        #
+        # Call the helper, which will return a dead frame object with
+        # the correct exception set, or MemoryError by default
+	# XXX make sure we return the correct value here
+        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
+        mc.BL(addr)
         self.gen_func_epilog(mc=mc)
         self.propagate_exception_path = mc.materialize(self.cpu.asmmemmgr, [])
 
         # restore registers and return 
         # We check for c.EQ here, meaning all bits zero in this case
         mc.POP([reg.value for reg in r.argument_regs] + [r.pc.value], cond=c.EQ)
-        # call on_leave_jitted_save_exc()
-        addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
+        #
+        # Call the helper, which will return a dead frame object with
+        # the correct exception set, or MemoryError by default
+        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
         mc.BL(addr)
         #
-        mc.gen_load_int(r.r0.value, self.cpu.propagate_exception_v)
-        #
         # footer -- note the ADD, which skips the return address of this
         # function, and will instead return to the caller's caller.  Note
         # also that we completely ignore the saved arguments, because we
 
     def setup_failure_recovery(self):
 
-        @rgc.no_collect
+        #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
         def failure_recovery_func(mem_loc, frame_pointer, stack_pointer):
             """mem_loc is a structure in memory describing where the values for
             the failargs are stored.  frame loc is the address of the frame
             pointer for the frame to be decoded frame """
-            vfp_registers = rffi.cast(rffi.LONGLONGP, stack_pointer)
-            registers = rffi.ptradd(vfp_registers, len(r.all_vfp_regs))
+            vfp_registers = rffi.cast(rffi.LONGP, stack_pointer)
+            registers = rffi.ptradd(vfp_registers, 2*len(r.all_vfp_regs))
             registers = rffi.cast(rffi.LONGP, registers)
-            return self.decode_registers_and_descr(mem_loc, frame_pointer,
+            bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+            return self.grab_frame_values(self.cpu, bytecode, frame_pointer,
                                                     registers, vfp_registers)
+        self.failure_recovery_code = [0, 0, 0, 0]
 
         self.failure_recovery_func = failure_recovery_func
 
-    recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed] * 3,
-                                                        lltype.Signed))
+    _FAILURE_RECOVERY_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP] * 3,
+                                                        llmemory.GCREF))
 
-    @rgc.no_collect
-    def decode_registers_and_descr(self, mem_loc, frame_pointer,
+    @staticmethod
+    #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
+    def grab_frame_values(cpu, bytecode, frame_pointer,
                                                 registers, vfp_registers):
-        """Decode locations encoded in memory at mem_loc and write the values
-        to the failboxes.  Values for spilled vars and registers are stored on
-        stack at frame_loc """
-        assert frame_pointer & 1 == 0
-        self.fail_force_index = frame_pointer
-        bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+        # no malloc allowed here!!  xxx apart from one, hacking a lot
+        force_index = rffi.cast(lltype.Signed, frame_pointer)
         num = 0
-        value = 0
-        fvalue = 0
+        deadframe = lltype.nullptr(jitframe.DEADFRAME)
+        # step 1: lots of mess just to count the final value of 'num'
+        bytecode1 = bytecode
+        while 1:
+            code = rffi.cast(lltype.Signed, bytecode1[0])
+            bytecode1 = rffi.ptradd(bytecode1, 1)
+            if code >= AssemblerARM.CODE_FROMSTACK:
+                while code > 0x7F:
+                    code = rffi.cast(lltype.Signed, bytecode1[0])
+                    bytecode1 = rffi.ptradd(bytecode1, 1)
+            else:
+                kind = code & 3
+                if kind == AssemblerARM.DESCR_SPECIAL:
+                    if code == AssemblerARM.CODE_HOLE:
+                        num += 1
+                        continue
+                    if code == AssemblerARM.CODE_INPUTARG:
+                        continue
+                    if code == AssemblerARM.CODE_FORCED:
+                        # resuming from a GUARD_NOT_FORCED
+                        token = force_index
+                        deadframe = (
+                            cpu.assembler.force_token_to_dead_frame.pop(token))
+                        deadframe = lltype.cast_opaque_ptr(
+                            jitframe.DEADFRAMEPTR, deadframe)
+                        continue
+                    assert code == AssemblerARM.CODE_STOP
+                    break
+            num += 1
+
+        # allocate the deadframe
+        if not deadframe:
+            # Remove the "reserve" at the end of the nursery.  This means
+            # that it is guaranteed that the following malloc() works
+            # without requiring a collect(), but it needs to be re-added
+            # as soon as possible.
+            cpu.gc_clear_extra_threshold()
+            assert num <= cpu.get_failargs_limit()
+            try:
+                deadframe = lltype.malloc(jitframe.DEADFRAME, num)
+            except MemoryError:
+                fatalerror("memory usage error in grab_frame_values")
+        # fill it
         code_inputarg = False
-        while True:
+        num = 0
+        value_hi = 0
+        while 1:
+            # decode the next instruction from the bytecode
             code = rffi.cast(lltype.Signed, bytecode[0])
             bytecode = rffi.ptradd(bytecode, 1)
-            if code >= self.CODE_FROMSTACK:
+            if code >= AssemblerARM.CODE_FROMSTACK:
                 if code > 0x7F:
                     shift = 7
                     code &= 0x7F
                             break
                 # load the value from the stack
                 kind = code & 3
-                code = int((code - self.CODE_FROMSTACK) >> 2)
+                code = (code - AssemblerARM.CODE_FROMSTACK) >> 2
                 if code_inputarg:
                     code = ~code
                     code_inputarg = False
-                if kind == self.DESCR_FLOAT:
-                    # we use code + 1 to get the hi word of the double worded float
-                    stackloc = frame_pointer - get_fp_offset(int(code) + 1)
-                    assert stackloc & 3 == 0
-                    fvalue = rffi.cast(rffi.LONGLONGP, stackloc)[0]
-                else:
-                    stackloc = frame_pointer - get_fp_offset(int(code))
-                    assert stackloc & 1 == 0
-                    value = rffi.cast(rffi.LONGP, stackloc)[0]
+                stackloc = force_index - get_fp_offset(int(code))
+                value = rffi.cast(rffi.LONGP, stackloc)[0]
+                if kind == AssemblerARM.DESCR_FLOAT:
+                    assert WORD == 4
+                    value_hi = value
+                    value = rffi.cast(rffi.LONGP, stackloc - WORD)[0]
             else:
-                # 'code' identifies a register: load its value
                 kind = code & 3
-                if kind == self.DESCR_SPECIAL:
-                    if code == self.CODE_HOLE:
+                if kind == AssemblerARM.DESCR_SPECIAL:
+                    if code == AssemblerARM.CODE_HOLE:
                         num += 1
                         continue
-                    if code == self.CODE_INPUTARG:
+                    if code == AssemblerARM.CODE_INPUTARG:
                         code_inputarg = True
                         continue
-                    assert code == self.CODE_STOP
+                    if code == AssemblerARM.CODE_FORCED:
+                        continue
+                    assert code == AssemblerARM.CODE_STOP
                     break
+                # 'code' identifies a register: load its value
                 code >>= 2
-                if kind == self.DESCR_FLOAT:
-                    fvalue = vfp_registers[code]
+                if kind == AssemblerARM.DESCR_FLOAT:
+                    if WORD == 4:
+                        value = vfp_registers[2*code]
+                        value_hi = vfp_registers[2*code + 1]
+                    else:
+                        value = registers[code]
                 else:
                     value = registers[code]
             # store the loaded value into fail_boxes_<type>
-            if kind == self.DESCR_FLOAT:
-                tgt = self.fail_boxes_float.get_addr_for_num(num)
-                rffi.cast(rffi.LONGLONGP, tgt)[0] = fvalue
+            if kind == AssemblerARM.DESCR_INT:
+                deadframe.jf_values[num].int = value
+            elif kind == AssemblerARM.DESCR_REF:
+                deadframe.jf_values[num].ref = rffi.cast(llmemory.GCREF, value)
+            elif kind == AssemblerARM.DESCR_FLOAT:
+                assert WORD == 4
+                assert not longlong.is_64_bit
+                floatvalue = rffi.cast(lltype.SignedLongLong, value_hi)
+                floatvalue <<= 32
+                floatvalue |= rffi.cast(lltype.SignedLongLong,
+                                        rffi.cast(lltype.Unsigned, value))
+                deadframe.jf_values[num].float = floatvalue
             else:
-                if kind == self.DESCR_INT:
-                    tgt = self.fail_boxes_int.get_addr_for_num(num)
-                elif kind == self.DESCR_REF:
-                    assert (value & 3) == 0, "misaligned pointer"
-                    tgt = self.fail_boxes_ptr.get_addr_for_num(num)
-                else:
-                    assert 0, "bogus kind"
-                rffi.cast(rffi.LONGP, tgt)[0] = value
+                assert 0, "bogus kind"
             num += 1
-        self.fail_boxes_count = num
+        #
+        assert num == len(deadframe.jf_values)
+        if not we_are_translated():
+            assert bytecode[4] == 0xCC
         fail_index = rffi.cast(rffi.INTP, bytecode)[0]
-        fail_index = rffi.cast(lltype.Signed, fail_index)
-        return fail_index
+        fail_descr = cpu.get_fail_descr_from_number(fail_index)
+        deadframe.jf_descr = fail_descr.hide(cpu)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, deadframe)
 
     def decode_inputargs(self, code):
         descr_to_box_type = [REF, INT, FLOAT]
         self.mc.CMP_ri(r.r0.value, 0)
         self.mc.B(self.propagate_exception_path, c=c.EQ)
 
-    def _gen_exit_path(self):
+    def _build_failure_recovery(self, exc, withfloats=False):
         mc = ARMv7Builder()
-        decode_registers_addr = llhelper(self.recovery_func_sign,
+        failure_recovery = llhelper(self._FAILURE_RECOVERY_FUNC,
                                             self.failure_recovery_func)
         self._insert_checks(mc)
-        with saved_registers(mc, r.all_regs, r.all_vfp_regs):
+        if withfloats:
+            f = r.all_vfp_regs
+        else:
+            f = []
+        with saved_registers(mc, r.all_regs, f):
+            if exc:
+                # We might have an exception pending.  Load it into r4
+                # (this is a register saved across calls)
+                mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
+                mc.LDR_ri(r.r4.value, self.cpu.pos_exc_value())
+                # clear the exc flags
+                mc.gen_load_int(r.r6.value, 0)
+                mc.STR_ri(r.r6.value, r.r5.value)
+                mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
+                mc.STR_ri(r.r6.value, r.r5.value)
             # move mem block address, to r0 to pass as
             mc.MOV_rr(r.r0.value, r.lr.value)
             # pass the current frame pointer as second param
             # pass the current stack pointer as third param
             mc.MOV_rr(r.r2.value, r.sp.value)
             self._insert_checks(mc)
-            mc.BL(rffi.cast(lltype.Signed, decode_registers_addr))
+            mc.BL(rffi.cast(lltype.Signed, failure_recovery))
+            if exc:
+                # save ebx into 'jf_guard_exc'
+                from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+                descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+                offset, size, _ = unpack_fielddescr(descrs.jf_guard_exc)
+                mc.STR_rr(r.r4.value, r.r0.value, offset, cond=c.AL)
             mc.MOV_rr(r.ip.value, r.r0.value)
         mc.MOV_rr(r.r0.value, r.ip.value)
         self.gen_func_epilog(mc=mc)
-        return mc.materialize(self.cpu.asmmemmgr, [],
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [],
                                    self.cpu.gc_ll_descr.gcrootmap)
+        self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+        self.mc = None
 
     DESCR_REF       = 0x00
     DESCR_INT       = 0x01
     DESCR_FLOAT     = 0x02
     DESCR_SPECIAL   = 0x03
     CODE_FROMSTACK  = 64
-    CODE_STOP       = 0 | DESCR_SPECIAL
-    CODE_HOLE       = 4 | DESCR_SPECIAL
-    CODE_INPUTARG   = 8 | DESCR_SPECIAL
+    CODE_STOP       = 0  | DESCR_SPECIAL
+    CODE_HOLE       = 4  | DESCR_SPECIAL
+    CODE_INPUTARG   = 8  | DESCR_SPECIAL
+    CODE_FORCED     = 12 | DESCR_SPECIAL #XXX where should this be written?
 
-    def gen_descr_encoding(self, descr, failargs, locs):
+    def write_failure_recovery_description(self, descr, failargs, locs):
         assert self.mc is not None
         for i in range(len(failargs)):
             arg = failargs[i]
             self.mc.writechar(chr(n))
         self.mc.writechar(chr(self.CODE_STOP))
 
-        fdescr = self.cpu.get_fail_descr_number(descr)
-        self.mc.write32(fdescr)
+
+    def generate_quick_failure(self, guardtok, fcond=c.AL):
+        assert isinstance(guardtok.save_exc, bool)
+        fail_index = self.cpu.get_fail_descr_number(guardtok.descr)
+        startpos = self.mc.currpos()
+        withfloats = False
+        for box in guardtok.failargs:
+            if box is not None and box.type == FLOAT:
+                withfloats = True
+                break
+        exc = guardtok.save_exc
+        target = self.failure_recovery_code[exc + 2 * withfloats]
+        assert target != 0
+        self.mc.BL(target)
+        # write tight data that describes the failure recovery
+        if guardtok.is_guard_not_forced:
+            self.mc.writechar(chr(self.CODE_FORCED))
+        self.write_failure_recovery_description(guardtok.descr,
+                                guardtok.failargs, guardtok.faillocs[1:])
+        self.mc.write32(fail_index)
+        # for testing the decoding, write a final byte 0xCC
+        if not we_are_translated():
+            self.mc.writechar('\xCC')
+            faillocs = [loc for loc in guardtok.faillocs if loc is not None]
+            guardtok.descr._arm_debug_faillocs = faillocs
         self.align()
-
-        # assert that the fail_boxes lists are big enough
-        assert len(failargs) <= self.fail_boxes_int.SIZE
-
-    def _gen_path_to_exit_path(self, descr, args, arglocs,
-                                            save_exc, fcond=c.AL):
-        assert isinstance(save_exc, bool)
-        self.gen_exit_code(self.mc, save_exc, fcond)
-        self.gen_descr_encoding(descr, args, arglocs[1:])
-
-    def gen_exit_code(self, mc, save_exc, fcond=c.AL):
-        assert isinstance(save_exc, bool)
-        if save_exc:
-            path = self._leave_jitted_hook_save_exc
-        else:
-            path = self._leave_jitted_hook
-        mc.BL(path)
+        return startpos
 
     def align(self):
         while(self.mc.currpos() % FUNC_ALIGN != 0):
 
     def write_pending_failure_recoveries(self):
         for tok in self.pending_guards:
-            descr = tok.descr
             #generate the exit stub and the encoded representation
-            pos = self.mc.currpos()
-            tok.pos_recovery_stub = pos
-
-            self._gen_path_to_exit_path(descr, tok.failargs,
-                                        tok.faillocs, save_exc=tok.save_exc)
+            tok.pos_recovery_stub = self.generate_quick_failure(tok)
             # store info on the descr
-            descr._arm_current_frame_depth = tok.faillocs[0].getint()
+            tok.descr._arm_current_frame_depth = tok.faillocs[0].getint()
 
     def process_pending_guards(self, block_start):
         clt = self.current_clt
             descr._arm_failure_recovery_block = failure_recovery_pos
             relative_offset = tok.pos_recovery_stub - tok.offset
             guard_pos = block_start + tok.offset
-            if not tok.is_invalidate:
+            if not tok.is_guard_not_invalidated:
                 # patch the guard jumpt to the stub
                 # overwrite the generate NOP with a B_offs to the pos of the
                 # stub
         else:
             raise AssertionError('Trying to pop to an invalid location')
 
-    def leave_jitted_hook(self):
-        ptrs = self.fail_boxes_ptr.ar
-        llop.gc_assume_young_pointers(lltype.Void,
-                                      llmemory.cast_ptr_to_adr(ptrs))
-
     def malloc_cond(self, nursery_free_adr, nursery_top_adr, size):
         assert size & (WORD-1) == 0     # must be correctly aligned
 

pypy/jit/backend/arm/opassembler.py

                                                 gen_emit_unary_float_op,
                                                 saved_registers,
                                                 count_reg_args)
+from pypy.jit.backend.arm.helper.regalloc import check_imm_arg
 from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
 from pypy.jit.backend.arm.jump import remap_frame_layout
 from pypy.jit.backend.arm.regalloc import TempInt, TempPtr
 from pypy.jit.metainterp.history import JitCellToken, TargetToken
 from pypy.jit.metainterp.resoperation import rop
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rpython.lltypesystem import rstr
+from pypy.rlib import rgc
+from pypy.rpython.lltypesystem import rstr, rffi, lltype, llmemory
 
 NO_FORCE_INDEX = -1
 
 
 class GuardToken(object):
-    def __init__(self, descr, failargs, faillocs, offset,
-                            save_exc, fcond=c.AL, is_invalidate=False):
+    def __init__(self, descr, failargs, faillocs, offset, save_exc, fcond=c.AL,
+		is_guard_not_invalidated=False, is_guard_not_forced=False):
         assert isinstance(save_exc, bool)
         self.descr = descr
         self.offset = offset
-        self.is_invalidate = is_invalidate
+        self.is_guard_not_invalidated = is_guard_not_invalidated
+        self.is_guard_not_forced = is_guard_not_forced
         self.failargs = failargs
         self.faillocs = faillocs
         self.save_exc = save_exc
         return fcond
 
     def _emit_guard(self, op, arglocs, fcond, save_exc,
-                                    is_guard_not_invalidated=False):
+                                    is_guard_not_invalidated=False, 
+                                    is_guard_not_forced=False):
         assert isinstance(save_exc, bool)
         assert isinstance(fcond, int)
         descr = op.getdescr()
                                     faillocs=arglocs,
                                     offset=pos,
                                     save_exc=save_exc,
-                                    is_invalidate=is_guard_not_invalidated,
+                                    is_guard_not_invalidated=is_guard_not_invalidated,
+                                    is_guard_not_forced=is_guard_not_forced,
                                     fcond=fcond))
         return c.AL
 
         return fcond
 
     def emit_op_finish(self, op, arglocs, regalloc, fcond):
-        for i in range(len(arglocs) - 1):
-            loc = arglocs[i]
-            box = op.getarg(i)
-            if loc is None:
-                continue
-            if loc.is_reg():
-                if box.type == REF:
-                    adr = self.fail_boxes_ptr.get_addr_for_num(i)
-                elif box.type == INT:
-                    adr = self.fail_boxes_int.get_addr_for_num(i)
-                else:
-                    assert 0
-                self.mc.gen_load_int(r.ip.value, adr)
-                self.mc.STR_ri(loc.value, r.ip.value)
-            elif loc.is_vfp_reg():
-                assert box.type == FLOAT
-                adr = self.fail_boxes_float.get_addr_for_num(i)
-                self.mc.gen_load_int(r.ip.value, adr)
-                self.mc.VSTR(loc.value, r.ip.value)
-            elif loc.is_stack() or loc.is_imm() or loc.is_imm_float():
-                if box.type == FLOAT:
-                    adr = self.fail_boxes_float.get_addr_for_num(i)
-                    self.mov_loc_loc(loc, r.vfp_ip)
-                    self.mc.gen_load_int(r.ip.value, adr)
-                    self.mc.VSTR(r.vfp_ip.value, r.ip.value)
-                elif box.type == REF or box.type == INT:
-                    if box.type == REF:
-                        adr = self.fail_boxes_ptr.get_addr_for_num(i)
-                    elif box.type == INT:
-                        adr = self.fail_boxes_int.get_addr_for_num(i)
-                    else:
-                        assert 0
-                    self.mov_loc_loc(loc, r.ip)
-                    self.mc.gen_load_int(r.lr.value, adr)
-                    self.mc.STR_ri(r.ip.value, r.lr.value)
-            else:
-                assert 0
-        # note: no exception should currently be set in llop.get_exception_addr
-        # even if this finish may be an exit_frame_with_exception (in this case
-        # the exception instance is in arglocs[0]).
-        addr = self.cpu.get_on_leave_jitted_int(save_exception=False)
-        self.mc.BL(addr)
-        self.mc.gen_load_int(r.r0.value, arglocs[-1].value)
+        [argloc] = arglocs
+        if argloc is not r.r0: #XXX verify this
+	    self.mov_loc_loc(argloc, r.r0, fcond)
+        # exit function
         self.gen_func_epilog()
         return fcond
 
                 value = self.cpu.done_with_this_frame_float_v
             else:
                 raise AssertionError(kind)
-        self.mc.gen_load_int(r.ip.value, value)
-        self.mc.CMP_rr(tmploc.value, r.ip.value)
+        from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+        from pypy.jit.backend.llsupport.descr import unpack_interiorfielddescr
+        descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+        _offset, _size, _ = unpack_fielddescr(descrs.jf_descr)
+        fail_descr = self.cpu.get_fail_descr_from_number(value)
+        value = fail_descr.hide(self.cpu)
+        rgc._make_sure_does_not_move(value)
+        value = rffi.cast(lltype.Signed, value)
+
+        if check_imm_arg(_offset):
+            self.mc.LDR_ri(r.ip.value, tmploc.value, imm=_offset)
+        else:
+            self.mc.gen_load_int(r.ip.value, _offset)
+            self.mc.LDR_rr(r.ip.value, tmploc.value, r.ip.value)
+        if check_imm_arg(value):
+            self.mc.CMP_ri(r.ip.value, imm=value)
+        else:
+            self.mc.gen_load_int(r.lr.value, value)
+            self.mc.CMP_rr(r.lr.value, r.ip.value)
+
 
         #if values are equal we take the fast path
         # Slow path, calling helper
         if op.result is not None:
             # load the return value from fail_boxes_xxx[0]
             kind = op.result.type
-            if kind == INT:
-                adr = self.fail_boxes_int.get_addr_for_num(0)
-            elif kind == REF:
-                adr = self.fail_boxes_ptr.get_addr_for_num(0)
-            elif kind == FLOAT:
-                adr = self.fail_boxes_float.get_addr_for_num(0)
+            if kind == FLOAT:
+                t = unpack_interiorfielddescr(descrs.as_float)[0]
+                if not check_imm_arg(t):
+                    self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+                    self.mc.ADD_rr(r.ip.value, r.r0.value, r.ip.value,
+                                          cond=fast_path_cond)
+                    t = 0
+                    base = r.ip
+                else:
+                    base = r.r0
+                self.mc.VLDR(resloc.value, base.value, imm=t,
+                                          cond=fast_path_cond)
             else:
-                raise AssertionError(kind)
-            self.mc.gen_load_int(r.ip.value, adr, cond=fast_path_cond)
-            if op.result.type == FLOAT:
-                self.mc.VLDR(resloc.value, r.ip.value, cond=fast_path_cond)
-            else:
-                self.mc.LDR_ri(resloc.value, r.ip.value, cond=fast_path_cond)
+                assert resloc is r.r0
+                if kind == INT:
+                    t = unpack_interiorfielddescr(descrs.as_int)[0]
+                else:
+                    t = unpack_interiorfielddescr(descrs.as_ref)[0]
+                if not check_imm_arg(t):
+                    self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+                    self.mc.LDR_rr(resloc.value, resloc.value, r.ip.value,
+                                          cond=fast_path_cond)
+                else:
+                    self.mc.LDR_ri(resloc.value, resloc.value, imm=t,
+                                          cond=fast_path_cond)
         # jump to merge point
         jmp_pos = self.mc.currpos()
         self.mc.BKPT()
 
         self.mc.LDR_ri(r.ip.value, r.fp.value)
         self.mc.CMP_ri(r.ip.value, 0)
-        self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE, save_exc=True)
+        self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE,
+                                   save_exc=True, is_guard_not_forced=True)
         return fcond
 
     def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc,

pypy/jit/backend/arm/regalloc.py

         return args
 
     def prepare_op_finish(self, op, fcond):
-        args = [None] * (op.numargs() + 1)
-        for i in range(op.numargs()):
-            arg = op.getarg(i)
-            if arg:
-                args[i] = self.loc(arg)
-                self.possibly_free_var(arg)
-        n = self.cpu.get_fail_descr_number(op.getdescr())
-        args[-1] = imm(n)
-        return args
+        loc = self.loc(op.getarg(0))
+        self.possibly_free_var(op.getarg(0))
+        return [loc]
 
     def prepare_op_guard_true(self, op, fcond):
         l0 = self.make_sure_var_in_reg(op.getarg(0))

pypy/jit/backend/arm/runner.py

         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
 
+        from pypy.jit.backend.llsupport import jitframe
+        self.deadframe_size_max = llmemory.sizeof(jitframe.DEADFRAME,
+                                                  self.get_failargs_limit())
+
     def set_debug(self, flag):
         return self.assembler.set_debug(flag)
 
+    def get_failargs_limit(self):
+        if self.opts is not None:
+            return self.opts.failargs_limit
+        else:
+            return 1000
+
     def setup(self):
-        if self.opts is not None:
-            failargs_limit = self.opts.failargs_limit
-        else:
-            failargs_limit = 1000
-        self.assembler = AssemblerARM(self, failargs_limit=failargs_limit)
+        self.assembler = AssemblerARM(self, self.translate_support_code)
 
     def setup_once(self):
         self.assembler.setup_once()
         return self.assembler.assemble_bridge(faildescr, inputargs, operations,
                                                 original_loop_token, log=log)
 
-    def get_latest_value_float(self, index):
-        return self.assembler.fail_boxes_float.getitem(index)
-
-    def get_latest_value_int(self, index):
-        return self.assembler.fail_boxes_int.getitem(index)
-
-    def get_latest_value_ref(self, index):
-        return self.assembler.fail_boxes_ptr.getitem(index)
-
-    def get_latest_value_count(self):
-        return self.assembler.fail_boxes_count
-
-    def get_latest_force_token(self):
-        return self.assembler.fail_force_index
-
-    def get_on_leave_jitted_hook(self):
-        return self.assembler.leave_jitted_hook
-
     def clear_latest_values(self, count):
         setitem = self.assembler.fail_boxes_ptr.setitem
         null = lltype.nullptr(llmemory.GCREF.TO)
             setitem(index, null)
 
     def make_execute_token(self, *ARGS):
-        FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
+        FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, llmemory.GCREF))
 
         def execute_token(executable_token, *args):
             clt = executable_token.compiled_loop_token
                 prev_interpreter = LLInterpreter.current_interpreter
                 LLInterpreter.current_interpreter = self.debug_ll_interpreter
             try:
-                fail_index = func(*args)
+                deadframe = func(*args)
             finally:
                 if not self.translate_support_code:
                     LLInterpreter.current_interpreter = prev_interpreter
             #llop.debug_print(lltype.Void, "<<<< Back")
-            return self.get_fail_descr_from_number(fail_index)
+            self.gc_set_extra_threshold()
+            return deadframe
         return execute_token
 
     def cast_ptr_to_int(x):
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
         rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
-        bytecode = self.assembler._find_failure_recovery_bytecode(faildescr)
+        frb = self.assembler._find_failure_recovery_bytecode(faildescr)
+        bytecode = rffi.cast(rffi.UCHARP, frb)
         addr_all_null_regsiters = rffi.cast(rffi.LONG, self.all_null_registers)
-        # start of "no gc operation!" block
-        fail_index_2 = self.assembler.failure_recovery_func(
-            bytecode,
-            addr_of_force_index,
-            addr_all_null_regsiters)
-        self.assembler.leave_jitted_hook()
-        # end of "no gc operation!" block
-        assert fail_index == fail_index_2
-        return faildescr
+        #
+        assert (rffi.cast(lltype.Signed, bytecode[0]) ==
+                self.assembler.CODE_FORCED)
+        bytecode = rffi.ptradd(bytecode, 1)
+        deadframe = self.assembler.grab_frame_values(self,
+                        bytecode, addr_of_force_index,
+                        self.all_null_registers,
+                        self.all_null_registers)
+        #
+        assert self.get_latest_descr(deadframe) is faildescr
+        self.assembler.force_token_to_dead_frame[addr_of_force_index] = (
+            deadframe)
+        return deadframe
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)

pypy/jit/backend/arm/test/test_loop_unroll.py

 import py
-from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+from pypy.jit.backend.arm.test.support import JitARMMixin
 from pypy.jit.metainterp.test import test_loop_unroll
 
-class TestLoopSpec(Jit386Mixin, test_loop_unroll.LoopUnrollTest):
+class TestLoopSpec(JitARMMixin, test_loop_unroll.LoopUnrollTest):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_loop.py
     pass

pypy/jit/backend/arm/test/test_runner.py

             ]
         cpu.compile_loop(inp, operations, looptoken)
         args = [i for i in range(1, 15)]
-        self.cpu.execute_token(looptoken, *args)
-        output = [self.cpu.get_latest_value_int(i - 1) for i in range(1, 15)]
+        deadframe = self.cpu.execute_token(looptoken, *args)
+        output = [self.cpu.get_latest_value_int(deadframe, i - 1) for i in range(1, 15)]
         expected = [3, 7, 11, 15, 19, 23, 27, 3, 7, 11, 15, 19, 23, 27]
         assert output == expected
 
-    def test_redirect_call_assember2(self):
-        def assembler_helper(failindex, virtualizable):
-            return self.cpu.get_latest_value_int(0)
+    def test_redirect_call_assembler2(self):
+        def assembler_helper(deadframe, virtualizable):
+            x = self.cpu.get_latest_value_int(deadframe, 0)
+            assert x == 11
+            return 7
 
-        FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
+        FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, llmemory.GCREF],
                                              lltype.Signed))
 
         class FakeJitDriverSD:
         self.cpu.compile_loop(loop2.inputargs, loop2.operations, lt2)
         self.cpu.compile_loop(loop3.inputargs, loop3.operations, lt3)
         self.cpu.compile_loop(loop1.inputargs, loop1.operations, lt1)
-        self.cpu.execute_token(lt1, 11)
-        assert self.cpu.get_latest_value_int(0) == 12
+        df = self.cpu.execute_token(lt1, 10)
+        assert self.cpu.get_latest_value_int(df, 0) == 7
 
         self.cpu.redirect_call_assembler(lt2, lt3)
-        self.cpu.execute_token(lt1, 11)
-        assert self.cpu.get_latest_value_int(0) == 10
+        df = self.cpu.execute_token(lt1, 12)
+        assert self.cpu.get_latest_value_int(df, 0) == 7
 
     SFloat = lltype.GcForwardReference()
     SFloat.become(lltype.GcStruct('SFloat', ('parent', rclass.OBJECT),
             ARGS = [lltype.Signed] * numargs
             RES = lltype.Signed
             args = [i+1 for i in range(numargs)]
-            res = self.cpu.execute_token(looptoken, *args)
-            assert self.cpu.get_latest_value_int(0) == sum(args)
+            deadframe = self.cpu.execute_token(looptoken, *args)
+            assert self.cpu.get_latest_value_int(deadframe, 0) == sum(args)
 
     def test_debugger_on(self):
         from pypy.rlib import debug

pypy/jit/backend/llgraph/runner.py

             try:
                 newbox = _cache[box]
             except KeyError:
-                newbox = _cache[box] = box.clonebox()
+                newbox = _cache[box] = box.__class__()
             return newbox
         #
         self.inputargs = map(mapping, inputargs)
         return res
 
     def execute_call_release_gil(self, descr, func, *args):
+        if hasattr(descr, '_original_func_'):
+            func = descr._original_func_     # see pyjitpl.py
+            # we want to call the function that does the aroundstate
+            # manipulation here (as a hack, instead of really doing
+            # the aroundstate manipulation ourselves)
+            return self.execute_call_may_force(descr, func, *args)
         call_args = support.cast_call_args_in_order(descr.ARGS, args)
         FUNC = lltype.FuncType(descr.ARGS, descr.RESULT)
         func_to_call = rffi.cast(lltype.Ptr(FUNC), func)

pypy/jit/backend/llsupport/llmodel.py

 
     # ------------------- helpers and descriptions --------------------
 
+    def gc_set_extra_threshold(self):
+        llop.gc_set_extra_threshold(lltype.Void, self.deadframe_size_max)
+
+    def gc_clear_extra_threshold(self):
+        llop.gc_set_extra_threshold(lltype.Void, 0)
+
     @staticmethod
     def _cast_int_to_gcref(x):
         # dangerous!  only use if you are sure no collection could occur

pypy/jit/backend/x86/runner.py

         else:
             return 1000
 
-    def gc_set_extra_threshold(self):
-        llop.gc_set_extra_threshold(lltype.Void, self.deadframe_size_max)
-
-    def gc_clear_extra_threshold(self):
-        llop.gc_set_extra_threshold(lltype.Void, 0)
-
     def setup(self):
         self.assembler = Assembler386(self, self.translate_support_code)
 

pypy/jit/codewriter/call.py

             if getattr(funcobj, 'graph', None) is None:
                 return 'residual'
             targetgraph = funcobj.graph
-            if (hasattr(targetgraph, 'func') and
-                hasattr(targetgraph.func, 'oopspec')):
-                return 'builtin'
+            if hasattr(targetgraph, 'func'):
+                # must never produce JitCode for a function with
+                # _gctransformer_hint_close_stack_ set!
+                if getattr(targetgraph.func,
+                           '_gctransformer_hint_close_stack_', False):
+                    return 'residual'
+                if hasattr(targetgraph.func, 'oopspec'):
+                    return 'builtin'
         elif op.opname == 'oosend':
             SELFTYPE, methname, opargs = support.decompose_oosend(op)
             if SELFTYPE.oopspec_name is not None:
         try:
             return self.jitcodes[graph]
         except KeyError:
+            # must never produce JitCode for a function with
+            # _gctransformer_hint_close_stack_ set!
+            if hasattr(graph, 'func') and getattr(graph.func,
+                    '_gctransformer_hint_close_stack_', False):
+                raise AssertionError(
+                    '%s has _gctransformer_hint_close_stack_' % (graph,))
+            #
             fnaddr, calldescr = self.get_jitcode_calldescr(graph)
             jitcode = JitCode(graph.name, fnaddr, calldescr,
                               called_from=called_from)
         # get the 'elidable' and 'loopinvariant' flags from the function object
         elidable = False
         loopinvariant = False
+        call_release_gil_target = llmemory.NULL
         if op.opname == "direct_call":
             funcobj = get_funcobj(op.args[0].value)
             assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
             if loopinvariant:
                 assert not NON_VOID_ARGS, ("arguments not supported for "
                                            "loop-invariant function!")
+            if getattr(func, "_call_aroundstate_target_", None):
+                call_release_gil_target = func._call_aroundstate_target_
+                call_release_gil_target = llmemory.cast_ptr_to_adr(
+                    call_release_gil_target)
         # build the extraeffect
         random_effects = self.randomeffects_analyzer.analyze(op)
         if random_effects:
         #
         effectinfo = effectinfo_from_writeanalyze(
             self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
-            oopspecindex, can_invalidate)
+            oopspecindex, can_invalidate, call_release_gil_target)
         #
         assert effectinfo is not None
         if elidable or loopinvariant:

pypy/jit/codewriter/effectinfo.py

 from pypy.jit.metainterp.typesystem import deref, fieldType, arrayItem
 from pypy.rpython.lltypesystem.rclass import OBJECT
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 from pypy.translator.backendopt.graphanalyze import BoolGraphAnalyzer
 
                 write_descrs_fields, write_descrs_arrays,
                 extraeffect=EF_CAN_RAISE,
                 oopspecindex=OS_NONE,
-                can_invalidate=False):
+                can_invalidate=False,
+                call_release_gil_target=llmemory.NULL):
         key = (frozenset_or_none(readonly_descrs_fields),
                frozenset_or_none(readonly_descrs_arrays),
                frozenset_or_none(write_descrs_fields),
                extraeffect,
                oopspecindex,
                can_invalidate)
+        if call_release_gil_target:
+            key += (object(),)    # don't care about caching in this case
         if key in cls._cache:
             return cls._cache[key]
         if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
         result.extraeffect = extraeffect
         result.can_invalidate = can_invalidate
         result.oopspecindex = oopspecindex
+        result.call_release_gil_target = call_release_gil_target
         if result.check_can_raise():
             assert oopspecindex in cls._OS_CANRAISE
         cls._cache[key] = result
     def has_random_effects(self):
         return self.extraeffect >= self.EF_RANDOM_EFFECTS
 
+    def is_call_release_gil(self):
+        return bool(self.call_release_gil_target)
+
 
 def frozenset_or_none(x):
     if x is None:
 def effectinfo_from_writeanalyze(effects, cpu,
                                  extraeffect=EffectInfo.EF_CAN_RAISE,
                                  oopspecindex=EffectInfo.OS_NONE,
-                                 can_invalidate=False):
+                                 can_invalidate=False,
+                                 call_release_gil_target=llmemory.NULL):
     from pypy.translator.backendopt.writeanalyze import top_set
     if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
         readonly_descrs_fields = None
                       write_descrs_arrays,
                       extraeffect,
                       oopspecindex,
-                      can_invalidate)
+                      can_invalidate,
+                      call_release_gil_target)
 
 def consider_struct(TYPE, fieldname):
     if fieldType(TYPE, fieldname) is lltype.Void:

pypy/jit/codewriter/test/test_call.py

 import py
 from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
-from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.translator.unsimplify import varoftype
 from pypy.rlib import jit
 from pypy.jit.codewriter.call import CallControl
     [op] = block.operations
     call_descr = cc.getcalldescr(op)
     assert call_descr.extrainfo.has_random_effects()
+    assert call_descr.extrainfo.is_call_release_gil() is False
+
+def test_call_release_gil():
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
+
+    T = rffi.CArrayPtr(rffi.TIME_T)
+    external = rffi.llexternal("time", [T], rffi.TIME_T, threadsafe=True)
+
+    # no jit.dont_look_inside in this test
+    def f():
+        return external(lltype.nullptr(T.TO))
+
+    rtyper = support.annotate(f, [])
+    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+    cc = CallControl(LLtypeCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+    res = cc.find_all_graphs(FakePolicy())
+
+    [llext_graph] = [x for x in res if x.func is external]
+    [block, _] = list(llext_graph.iterblocks())
+    [op] = block.operations
+    call_target = op.args[0].value._obj.graph.func._call_aroundstate_target_
+    call_target = llmemory.cast_ptr_to_adr(call_target)
+    call_descr = cc.getcalldescr(op)
+    assert call_descr.extrainfo.has_random_effects()
+    assert call_descr.extrainfo.is_call_release_gil() is True
+    assert call_descr.extrainfo.call_release_gil_target == call_target
 
 def test_random_effects_on_stacklet_switch():
     from pypy.jit.backend.llgraph.runner import LLGraphCPU

pypy/jit/metainterp/pyjitpl.py

             self.metainterp.vable_and_vrefs_before_residual_call()
             resbox = self.metainterp.execute_and_record_varargs(
                 rop.CALL_MAY_FORCE, allboxes, descr=descr)
+            if effectinfo.is_call_release_gil():
+                self.metainterp.direct_call_release_gil()
             self.metainterp.vrefs_after_residual_call()
             vablebox = None
             if assembler_call:
             if vablebox is not None:
                 self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None)
             self.metainterp.handle_possible_exception()
+            # XXX refactor: direct_libffi_call() is a hack
             if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL:
                 self.metainterp.direct_libffi_call()
             return resbox
                                 [box_resultpos, ConstInt(0), box_result],
                                 None, descr)
 
+    def direct_call_release_gil(self):
+        op = self.history.operations.pop()
+        assert op.opnum == rop.CALL_MAY_FORCE
+        descr = op.getdescr()
+        effectinfo = descr.get_extra_info()
+        realfuncaddr = effectinfo.call_release_gil_target
+        funcbox = ConstInt(heaptracker.adr2int(realfuncaddr))
+        self.history.record(rop.CALL_RELEASE_GIL,
+                            [funcbox] + op.getarglist()[1:],
+                            op.result, descr)
+        if not we_are_translated():       # for llgraph
+            descr._original_func_ = op.getarg(0).value
+
 # ____________________________________________________________
 
 class ChangeFrame(JitException):

pypy/jit/metainterp/test/test_ajit.py

             rgc.add_memory_pressure(1234)
             return 3
 
-        self.interp_operations(f, [])
+    def test_external_call(self):
+        from pypy.rlib.objectmodel import invoke_around_extcall
         
+        T = rffi.CArrayPtr(rffi.TIME_T)
+        external = rffi.llexternal("time", [T], rffi.TIME_T)
+
+        class Oups(Exception):
+            pass
+        class State:
+            pass
+        state = State()
+
+        def before():
+            if we_are_jitted():
+                raise Oups
+            state.l.append("before")
+
+        def after():
+            if we_are_jitted():
+                raise Oups
+            state.l.append("after")
+
+        def f():
+            state.l = []
+            invoke_around_extcall(before, after)
+            external(lltype.nullptr(T.TO))
+            return len(state.l)
+
+        res = self.interp_operations(f, [])
+        assert res == 2
+        res = self.interp_operations(f, [])
+        assert res == 2
+        self.check_operations_history(call_release_gil=1, call_may_force=0)

pypy/module/README.txt

 that require access to interpreter level.  See here
 for more information: 
 
-    http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#modules-in-pypy
+    http://doc.pypy.org/en/latest/coding-guide.html#modules-in-pypy
 
 ATTENTION: don't put any '.py' files directly into pypy/module 
 because you can easily get import mixups on e.g. "import sys" 

pypy/module/_sre/interp_sre.py

     result = [-1] * (2 * num_groups)
     mark = ctx.match_marks
     while mark is not None:
-        index = mark.gid
+        index = jit.promote(mark.gid)
         if result[index] == -1:
             result[index] = mark.position
         mark = mark.prev
 # SRE_Pattern class
 
 class W_SRE_Pattern(Wrappable):
-    _immutable_fields_ = ["code", "flags", "num_groups"]
+    _immutable_fields_ = ["code", "flags", "num_groups", "w_groupindex"]
 
     def cannot_copy_w(self):
         space = self.space

pypy/module/sys/app.py

     return None
 
 copyright_str = """
-Copyright 2003-2012 PyPy development team.
+Copyright 2003-2013 PyPy development team.
 All Rights Reserved.
 For further information, see <http://pypy.org>
 
-Portions Copyright (c) 2001-2012 Python Software Foundation.
+Portions Copyright (c) 2001-2013 Python Software Foundation.
 All Rights Reserved.
 
 Portions Copyright (c) 2000 BeOpen.com.

pypy/rpython/lltypesystem/rffi.py

         call_external_function._dont_inline_ = True
         call_external_function._annspecialcase_ = 'specialize:ll'
         call_external_function._gctransformer_hint_close_stack_ = True
+        call_external_function._call_aroundstate_target_ = funcptr
         call_external_function = func_with_new_name(call_external_function,
                                                     'ccall_' + name)
         # don't inline, as a hack to guarantee that no GC pointer is alive

pypy/tool/option.py

 import optparse
 
 extra_useage = """For detailed descriptions of all the options see
-http://codespeak.net/pypy/dist/pypy/doc/config/commandline.html"""
+http://doc.pypy.org/en/latest/config/commandline.html"""
 
 def get_standard_options():
     config = get_pypy_config()

pypy/tool/release/make_release.py

-#!/usr/bin/env python
-
-""" A tool to download correct pypy-c's from nightly build run and package them
-into release packages. Note: you must run apropriate buildbots first and
-make sure there are no failures. Use force-builds.py from the same directory.
-
-Usage: make_release.py  <branchname>  <version>
- e.g.: make_release.py  release-1.4.1  1.4.1
-"""
-
-import autopath
-import sys
-import urllib2
-from xml.dom import minidom
-import re
-import py
-from pypy.tool.udir import udir
-from pypy.tool.release.package import package
-import tarfile
-import os
-import shutil
-
-BASEURL = 'http://buildbot.pypy.org/nightly/'
-PAUSE = False
-
-def browse_nightly(branch,
-                   baseurl=BASEURL,
-                   override_xml=None):
-    if override_xml is None:
-        url = baseurl + branch + '/'
-        xml = urllib2.urlopen(url).read()
-    else:
-        xml = override_xml
-    dom = minidom.parseString(xml)
-    refs = [node.getAttribute('href') for node in dom.getElementsByTagName('a')
-            if 'pypy' in node.getAttribute('href')]
-    # all refs are of form: pypy-c-{type}-{revnum}-{hghash}-{platform}.tar.bz2
-    r = re.compile('pypy-c-([\w\d]+)-(\d+)-([0-9a-f]+)-([\w\d]+).tar.bz2$')
-    d = {}
-    for ref in refs:
-        kind, revnum, hghash, platform = r.match(ref).groups()
-        rev = int(revnum)
-        try:
-            lastrev, _ = d[(kind, platform)]
-        except KeyError:
-            lastrev = -1
-        if rev > lastrev:
-            d[(kind, platform)] = rev, ref
-    return d
-
-def main(branch, release):
-    to_download = browse_nightly(branch)
-    tmpdir = udir.join('download')
-    tmpdir.ensure(dir=True)
-    alltars = []
-    olddir = os.getcwd()
-    try:
-        os.chdir(str(tmpdir))
-        print 'Using tmpdir', str(tmpdir)
-        for (kind, platform), (rev, name) in to_download.iteritems():
-            if platform == 'win32':
-                print 'Ignoring %s, windows unsupported' % name
-            else:
-                print "Downloading %s at rev %d" % (name, rev)
-                url = BASEURL + branch + "/" + name
-                data = urllib2.urlopen(url).read()
-                tmpdir.join(name).write(data, mode="wb")
-                t = tarfile.open(str(tmpdir.join(name)))
-                dirname = t.getmembers()[0].name
-                t.extractall(path=str(tmpdir))
-                if kind == 'jit':
-                    kind = ''
-                else:
-                    kind = '-' + kind
-                topdirname = 'pypy-%s-%s%s' % (release, platform, kind)
-                os.system('mv %s %s' % (str(tmpdir.join(dirname)),
-                                        str(tmpdir.join(topdirname))))
-                if PAUSE:
-                    print 'Pausing, press Enter...'
-                    raw_input()
-                name = '%s.tar.bz2' % topdirname
-                print "Building %s" % name
-                t = tarfile.open(name, 'w:bz2')
-                t.add(topdirname)
-                alltars.append(name)
-                t.close()
-                shutil.rmtree(str(tmpdir.join(topdirname)))
-        for name in alltars:
-            print "Uploading %s" % name
-            os.system('scp %s codespeak.net:/www/pypy.org/htdocs/download' % name)
-    finally:
-        os.chdir(olddir)
-
-if __name__ == '__main__':
-    if len(sys.argv) != 3:
-        print __doc__
-        sys.exit(1)
-    main(sys.argv[1], release=sys.argv[2])
-    

pypy/tool/release/package.py

     try:
         os.chdir(str(builddir))
         #
-        # 'strip' fun: see https://codespeak.net/issue/pypy-dev/issue587
+        # 'strip' fun: see issue #587
         for source, target in binaries:
             if sys.platform == 'win32':
                 pass
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.