Commits

Alex Perry  committed 764360b Merge

merge code changes

  • Participants
  • Parent commits 9abd94c, 9ab6cbb

Comments (0)

Files changed (10)

File pypy/jit/backend/x86/assembler.py

                 else:
                     get_from_stack.append((floc, True))
 
-        remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG)
-        remap_frame_layout(self, xmm_src_locs, xmm_dst_locs, X86_64_XMM_SCRATCH_REG)
+        remap_frame_layout(self,
+                           src_locs + xmm_src_locs,
+                           dst_locs + xmm_dst_locs,
+                           X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG)
 
         for i in range(len(get_from_stack)):
             loc, is_xmm = get_from_stack[i]
                     self.mc.MOV_sr(i*WORD, loc.value)
 
         # Handle register arguments
-        remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG)
-        remap_frame_layout(self, xmm_src_locs, xmm_dst_locs, X86_64_XMM_SCRATCH_REG)
+        remap_frame_layout(self,
+                           src_locs + xmm_src_locs,
+                           dst_locs + xmm_dst_locs,
+                           X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG)
 
         self._regalloc.reserve_param(len(pass_on_stack))
         self.mc.CALL(x)
             # arglocs[2:] too, so they are saved on the stack above and
             # restored below.
             remap_frame_layout(self, arglocs[:2], [edi, esi],
-                               X86_64_SCRATCH_REG)
+                               X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG)
 
         # misaligned stack in the call, but it's ok because the write barrier
         # is not going to call anything more.  Also, this assumes that the

File pypy/jit/backend/x86/jump.py

 from pypy.tool.pairtype import extendabletype
 from pypy.jit.backend.x86.regloc import ImmedLoc, StackLoc
 
-def remap_frame_layout(assembler, src_locations, dst_locations, tmpreg):
-    pending_dests = len(dst_locations)
-    srccount = {}    # maps dst_locations to how many times the same
-                     # location appears in src_locations
-    for dst in dst_locations:
-        key = dst._getregkey()
-        assert key not in srccount, "duplicate value in dst_locations!"
-        srccount[key] = 0
-    for i in range(len(dst_locations)):
-        src = src_locations[i]
-        if isinstance(src, ImmedLoc):
-            continue
-        key = src._getregkey()
-        if key in srccount:
-            if key == dst_locations[i]._getregkey():
-                srccount[key] = -sys.maxint     # ignore a move "x = x"
-                pending_dests -= 1
-            else:
-                srccount[key] += 1
 
-    while pending_dests > 0:
-        progress = False
+class JumpRemapper(object):
+
+    def move(self, src, dst):
+        """Called to generate a move from src to dst."""
+        raise NotImplementedError
+
+    def push(self, src):
+        """Called to temporarily save away the value of src."""
+        raise NotImplementedError
+
+    def pop(self, dst):
+        """Called after push() to restore the saved value into dst."""
+        raise NotImplementedError
+
+    def remap_frame_layout(self, src_locations, dst_locations):
+        pending_dests = len(dst_locations)
+        srccount = {}    # maps dst_locations to how many times the same
+                         # location appears in src_locations
+        for dst in dst_locations:
+            key = dst._getregkey()
+            assert key not in srccount, "duplicate value in dst_locations!"
+            srccount[key] = 0
         for i in range(len(dst_locations)):
-            dst = dst_locations[i]
-            key = dst._getregkey()
-            if srccount[key] == 0:
-                srccount[key] = -1       # means "it's done"
-                pending_dests -= 1
-                src = src_locations[i]
-                if not isinstance(src, ImmedLoc):
-                    key = src._getregkey()
-                    if key in srccount:
-                        srccount[key] -= 1
-                _move(assembler, src, dst, tmpreg)
-                progress = True
-        if not progress:
-            # we are left with only pure disjoint cycles
-            sources = {}     # maps dst_locations to src_locations
-            for i in range(len(dst_locations)):
-                src = src_locations[i]
-                dst = dst_locations[i]
-                sources[dst._getregkey()] = src
-            #
+            src = src_locations[i]
+            if isinstance(src, ImmedLoc):
+                continue
+            key = src._getregkey()
+            if key in srccount:
+                if key == dst_locations[i]._getregkey():
+                    srccount[key] = -sys.maxint     # ignore a move "x = x"
+                    pending_dests -= 1
+                else:
+                    srccount[key] += 1
+
+        while pending_dests > 0:
+            progress = False
             for i in range(len(dst_locations)):
                 dst = dst_locations[i]
-                originalkey = dst._getregkey()
-                if srccount[originalkey] >= 0:
-                    assembler.regalloc_push(dst)
-                    while True:
-                        key = dst._getregkey()
-                        assert srccount[key] == 1
-                        # ^^^ because we are in a simple cycle
-                        srccount[key] = -1
-                        pending_dests -= 1
-                        src = sources[key]
-                        if src._getregkey() == originalkey:
-                            break
-                        _move(assembler, src, dst, tmpreg)
-                        dst = src
-                    assembler.regalloc_pop(dst)
-            assert pending_dests == 0
+                key = dst._getregkey()
+                if srccount[key] == 0:
+                    srccount[key] = -1       # means "it's done"
+                    pending_dests -= 1
+                    src = src_locations[i]
+                    if not isinstance(src, ImmedLoc):
+                        key = src._getregkey()
+                        if key in srccount:
+                            srccount[key] -= 1
+                    self.move(src, dst)
+                    progress = True
+            if not progress:
+                # we are left with only pure disjoint cycles
+                sources = {}     # maps dst_locations to src_locations
+                for i in range(len(dst_locations)):
+                    src = src_locations[i]
+                    dst = dst_locations[i]
+                    sources[dst._getregkey()] = src
+                #
+                for i in range(len(dst_locations)):
+                    dst = dst_locations[i]
+                    originalkey = dst._getregkey()
+                    if srccount[originalkey] >= 0:
+                        self.push(dst)
+                        while True:
+                            key = dst._getregkey()
+                            assert srccount[key] == 1
+                            # ^^^ because we are in a simple cycle
+                            srccount[key] = -1
+                            pending_dests -= 1
+                            src = sources[key]
+                            if src._getregkey() == originalkey:
+                                break
+                            self.move(src, dst)
+                            dst = src
+                        self.pop(dst)
+                assert pending_dests == 0
 
-def _move(assembler, src, dst, tmpreg):
-    if dst.is_memory_reference() and src.is_memory_reference():
-        assembler.regalloc_mov(src, tmpreg)
-        src = tmpreg
-    assembler.regalloc_mov(src, dst)
+
+class ConcreteJumpRemapper(JumpRemapper):
+
+    def get_tmp_reg(self, dst):
+        """Get a temporary register suitable for copying into dst."""
+        raise NotImplementedError
+
+    def move(self, src, dst):
+        if dst.is_memory_reference() and src.is_memory_reference():
+            tmpreg = self.get_tmp_reg(dst)
+            self.simple_move(src, tmpreg)
+            src = tmpreg
+        self.simple_move(src, dst)
+
+    def simple_move(self, src, dst):
+        raise NotImplementedError
+
+
+class X86JumpRemapper(ConcreteJumpRemapper):
+    def __init__(self, assembler, tmp, xmmtmp):
+        self.assembler = assembler
+        self.tmpreg = tmp
+        self.xmmtmpreg = xmmtmp
+
+    def get_tmp_reg(self, dst):
+        if dst.is_xmm_location():
+            return self.xmmtmpreg
+        else:
+            return self.tmpreg
+
+    def simple_move(self, src, dst):
+        self.assembler.regalloc_mov(src, dst)
+
+    def push(self, src):
+        self.assembler.regalloc_push(src)
+
+    def pop(self, dst):
+        self.assembler.regalloc_pop(dst)
+
+def remap_frame_layout(assembler, src_locations, dst_locations, tmp, xmmtmp):
+    # X86-specific logic
+    remapper = X86JumpRemapper(assembler, tmp, xmmtmp)
+    remapper.remap_frame_layout(src_locations, dst_locations)

File pypy/jit/backend/x86/regalloc.py

         xmmtmploc = self.xrm.force_allocate_reg(box1, selected_reg=xmmtmp)
         # Part about non-floats
         # XXX we don't need a copy, we only just the original list
-        src_locations = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
+        src_locations1 = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
                          if op.getarg(i).type != FLOAT]
         assert tmploc not in nonfloatlocs
-        dst_locations = [loc for loc in nonfloatlocs if loc is not None]
-        remap_frame_layout(assembler, src_locations, dst_locations, tmploc)
+        dst_locations1 = [loc for loc in nonfloatlocs if loc is not None]
         # Part about floats
-        src_locations = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
+        src_locations2 = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
                          if op.getarg(i).type == FLOAT]
-        dst_locations = [loc for loc in floatlocs if loc is not None]
-        remap_frame_layout(assembler, src_locations, dst_locations, xmmtmp)
+        dst_locations2 = [loc for loc in floatlocs if loc is not None]
+        # Do the remapping
+        remap_frame_layout(assembler,
+                           src_locations1 + src_locations2,
+                           dst_locations1 + dst_locations2,
+                           tmploc, xmmtmp)
         self.rm.possibly_free_var(box)
         self.xrm.possibly_free_var(box1)
         self.possibly_free_vars_for_op(op)

File pypy/jit/backend/x86/regloc.py

 
     def find_unused_reg(self): return eax
 
+    def is_xmm_location(self): raise NotImplementedError
+
 class StackLoc(AssemblerLocation):
     _immutable_ = True
     def __init__(self, position, ebp_offset, num_words, type):
         # One of INT, REF, FLOAT
         self.type = type
 
+    def is_xmm_location(self):
+        return self.type == FLOAT
+
     def frame_size(self):
         return self.width // WORD
 
             self.width = 8
         else:
             self.width = WORD
+
     def __repr__(self):
         if self.is_xmm:
             return rx86.R.xmmnames[self.value]
         else:
             return rx86.R.names[self.value]
 
+    def _getregkey(self):
+        return (self.value << 1) | self.is_xmm
+
+    def is_xmm_location(self):
+        return self.is_xmm
+
     def lowest8bits(self):
         assert not self.is_xmm
         return RegLoc(rx86.low_byte(self.value), False)

File pypy/jit/backend/x86/test/test_jump.py

 from pypy.jit.backend.x86.regloc import *
 from pypy.jit.backend.x86.regalloc import X86FrameManager
-from pypy.jit.backend.x86.jump import remap_frame_layout
+from pypy.jit.backend.x86.jump import ConcreteJumpRemapper
 from pypy.jit.metainterp.history import INT
 
 frame_pos = X86FrameManager.frame_pos
 
-class MockAssembler:
-    def __init__(self):
+class MockAssembler(ConcreteJumpRemapper):
+    def __init__(self, tmpreg='?'):
         self.ops = []
+        self.tmpreg = tmpreg
 
-    def regalloc_mov(self, from_loc, to_loc):
+    def get_tmp_reg(self, src):
+        return self.tmpreg
+
+    def simple_move(self, from_loc, to_loc):
         self.ops.append(('mov', from_loc, to_loc))
 
-    def regalloc_push(self, loc):
+    def push(self, loc):
         self.ops.append(('push', loc))
 
-    def regalloc_pop(self, loc):
+    def pop(self, loc):
         self.ops.append(('pop', loc))
 
     def got(self, expected):
 
 def test_trivial():
     assembler = MockAssembler()
-    remap_frame_layout(assembler, [], [], '?')
+    assembler.remap_frame_layout([], [])
     assert assembler.ops == []
-    remap_frame_layout(assembler, [eax, ebx, ecx, edx, esi, edi],
-                                  [eax, ebx, ecx, edx, esi, edi], '?')
+    assembler.remap_frame_layout([eax, ebx, ecx, edx, esi, edi],
+                                 [eax, ebx, ecx, edx, esi, edi])
     assert assembler.ops == []
     s8 = frame_pos(1, INT)
     s12 = frame_pos(31, INT)
     s20 = frame_pos(6, INT)
-    remap_frame_layout(assembler, [eax, ebx, ecx, s20, s8, edx, s12, esi, edi],
-                                  [eax, ebx, ecx, s20, s8, edx, s12, esi, edi],
-                                  '?')
+    assembler.remap_frame_layout([eax, ebx, ecx, s20, s8, edx, s12, esi, edi],
+                                 [eax, ebx, ecx, s20, s8, edx, s12, esi, edi])
     assert assembler.ops == []
 
 def test_simple_registers():
     assembler = MockAssembler()
-    remap_frame_layout(assembler, [eax, ebx, ecx], [edx, esi, edi], '?')
+    assembler.remap_frame_layout([eax, ebx, ecx], [edx, esi, edi])
     assert assembler.ops == [('mov', eax, edx),
                              ('mov', ebx, esi),
                              ('mov', ecx, edi)]
 
 def test_simple_framelocs():
-    assembler = MockAssembler()
+    assembler = MockAssembler(edx)
     s8 = frame_pos(0, INT)
     s12 = frame_pos(13, INT)
     s20 = frame_pos(20, INT)
     s24 = frame_pos(221, INT)
-    remap_frame_layout(assembler, [s8, eax, s12], [s20, s24, edi], edx)
+    assembler.remap_frame_layout([s8, eax, s12], [s20, s24, edi])
     assert assembler.ops == [('mov', s8, edx),
                              ('mov', edx, s20),
                              ('mov', eax, s24),
     s12 = frame_pos(12, INT)
     s20 = frame_pos(19, INT)
     s24 = frame_pos(1, INT)
-    remap_frame_layout(assembler, [eax, s8, s20, ebx],
-                                  [s8, ebx, eax, edi], '?')
+    assembler.remap_frame_layout([eax, s8, s20, ebx],
+                                 [s8, ebx, eax, edi])
     assert assembler.got([('mov', ebx, edi),
                           ('mov', s8, ebx),
                           ('mov', eax, s8),
     s12 = frame_pos(12, INT)
     s20 = frame_pos(19, INT)
     s24 = frame_pos(1, INT)
-    remap_frame_layout(assembler, [eax, s8, s20, ebx],
-                                  [s8, ebx, eax, s20], '?')
+    assembler.remap_frame_layout([eax, s8, s20, ebx],
+                                 [s8, ebx, eax, s20])
     assert assembler.got([('push', s8),
                           ('mov', eax, s8),
                           ('mov', s20, eax),
                           ('pop', ebx)])
 
 def test_cycle_2():
-    assembler = MockAssembler()
+    assembler = MockAssembler(ecx)
     s8 = frame_pos(8, INT)
     s12 = frame_pos(12, INT)
     s20 = frame_pos(19, INT)
     s24 = frame_pos(1, INT)
     s2 = frame_pos(2, INT)
     s3 = frame_pos(3, INT)
-    remap_frame_layout(assembler,
+    assembler.remap_frame_layout(
                        [eax, s8, edi, s20, eax, s20, s24, esi, s2, s3],
-                       [s8, s20, edi, eax, edx, s24, ebx, s12, s3, s2],
-                       ecx)
+                       [s8, s20, edi, eax, edx, s24, ebx, s12, s3, s2])
     assert assembler.got([('mov', eax, edx),
                           ('mov', s24, ebx),
                           ('mov', esi, s12),
 def test_constants():
     assembler = MockAssembler()
     c3 = imm(3)
-    remap_frame_layout(assembler, [c3], [eax], '?')
+    assembler.remap_frame_layout([c3], [eax])
     assert assembler.ops == [('mov', c3, eax)]
     assembler = MockAssembler()
     s12 = frame_pos(12, INT)
-    remap_frame_layout(assembler, [c3], [s12], '?')
+    assembler.remap_frame_layout([c3], [s12])
     assert assembler.ops == [('mov', c3, s12)]
 
 def test_constants_and_cycle():
-    assembler = MockAssembler()
+    assembler = MockAssembler(edi)
     c3 = imm(3)
     s12 = frame_pos(13, INT)
-    remap_frame_layout(assembler, [ebx, c3,  s12],
-                                  [s12, eax, ebx], edi)
+    assembler.remap_frame_layout([ebx, c3,  s12],
+                                 [s12, eax, ebx])
     assert assembler.ops == [('mov', c3, eax),
                              ('push', s12),
                              ('mov', ebx, s12),

File pypy/module/pypyjit/test_pypy_c/model.py

         # replaced with the corresponding operations, so that tests don't have
         # to repeat it every time
         ticker_check = """
-            ticker0 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+            ticker0 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
             ticker1 = int_sub(ticker0, 1)
-            setfield_raw(ticker_address, ticker1, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+            setfield_raw(ticker_address, ticker1, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
             ticker_cond = int_lt(ticker1, 0)
             guard_false(ticker_cond, descr=...)
         """
             self.alpha_map[v1] = exp_v2
         return self.alpha_map[v1] == exp_v2
 
+    def match_descr(self, descr, exp_descr):
+        if descr == exp_descr or exp_descr == '...':
+            return True
+        match = exp_descr is not None and re.match(exp_descr, descr)
+        self._assert(match, "descr mismatch")
+
     def _assert(self, cond, message):
         if not cond:
             raise InvalidMatch(message, frame=sys._getframe(1))
         self._assert(len(op.args) == len(exp_args), "wrong number of arguments")
         for arg, exp_arg in zip(op.args, exp_args):
             self._assert(self.match_var(arg, exp_arg), "variable mismatch")
-        self._assert(op.descr == exp_descr or exp_descr == '...', "descr mismatch")
+        self.match_descr(op.descr, exp_descr)
+        
 
     def _next_op(self, iter_ops, assert_raises=False):
         try:

File pypy/module/pypyjit/test_pypy_c/test_model.py

         """
         assert self.match(loop, "setfield_gc(p0, 1, descr=<foobar>)")
         assert self.match(loop, "setfield_gc(p0, 1, descr=...)")
+        assert self.match(loop, "setfield_gc(p0, 1, descr=<.*bar>)")
         assert not self.match(loop, "setfield_gc(p0, 1)")
         assert not self.match(loop, "setfield_gc(p0, 1, descr=<zzz>)")
 
             guard_true(i6, descr=...)
             i8 = int_add(i4, 1)
             # signal checking stuff
-            i10 = getfield_raw(37212896, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+            i10 = getfield_raw(37212896, descr=<.* pypysig_long_struct.c_value .*>)
             i12 = int_sub(i10, 1)
-            setfield_raw(37212896, i12, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+            setfield_raw(37212896, i12, descr=<.* pypysig_long_struct.c_value .*>)
             i14 = int_lt(i12, 0)
             guard_false(i14, descr=...)
             jump(p0, p1, p2, p3, i8, descr=...)

File pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py

         assert log.opnames(ops) == ["getfield_gc", "guard_nonnull_class"]
         #
         assert entry_bridge.match_by_id('call', """
-            p29 = getfield_gc(ConstPtr(ptr28), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value 8>)
+            p29 = getfield_gc(ConstPtr(ptr28), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value .*>)
             guard_nonnull_class(p29, ConstClass(Function), descr=<Guard17>)
-            i32 = getfield_gc(p0, descr=<BoolFieldDescr pypy.interpreter.pyframe.PyFrame.inst_is_being_profiled 161>)
+            i32 = getfield_gc(p0, descr=<BoolFieldDescr pypy.interpreter.pyframe.PyFrame.inst_is_being_profiled .*>)
             guard_false(i32, descr=<Guard18>)
-            p33 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_code 24>)
+            p33 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_code .*>)
             guard_value(p33, ConstPtr(ptr34), descr=<Guard19>)
-            p35 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_w_func_globals 64>)
-            p36 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_closure 16>)
+            p35 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_w_func_globals .*>)
+            p36 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_closure .*>)
             p38 = call(ConstClass(getexecutioncontext), descr=<GcPtrCallDescr>)
-            p39 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref 56>)
+            p39 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
             i40 = force_token()
-            p41 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc 72>)
+            p41 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
             guard_isnull(p41, descr=<Guard20>)
-            i42 = getfield_gc(p38, descr=<NonGcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc 40>)
+            i42 = getfield_gc(p38, descr=<NonGcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
             i43 = int_is_zero(i42)
             guard_true(i43, descr=<Guard21>)
             i50 = force_token()

File pypy/objspace/std/mapdict.py

         return index
 
     def _index(self, selector):
+        while isinstance(self, PlainAttribute):
+            if selector == self.selector:
+                return self.position
+            self = self.back
         return -1
 
     def copy(self, obj):
             self._copy_attr(obj, new_obj)
         return new_obj
 
-    def _index(self, selector):
-        if selector == self.selector:
-            return self.position
-        return self.back._index(selector)
-
     def copy(self, obj):
         new_obj = self.back.copy(obj)
         self._copy_attr(obj, new_obj)

File pypy/objspace/std/test/test_mapdict.py

 
     assert aa.get_terminator() is aa.back.back
 
+def test_huge_chain():
+    current = Terminator(space, "cls")
+    for i in range(20000):
+        current = PlainAttribute((str(i), DICT), current)
+    assert current.index(("0", DICT)) == 0
+
+
 def test_search():
     aa = PlainAttribute(("b", DICT), PlainAttribute(("a", DICT), Terminator(None, None)))
     assert aa.search(DICT) is aa