[pypy-svn] r73415 - in pypy/branch/jit-stackless/pypy/jit: backend/llgraph backend/x86 backend/x86/test metainterp/test

iammisc at codespeak.net iammisc at codespeak.net
Mon Apr 5 18:48:40 CEST 2010


Author: iammisc
Date: Mon Apr  5 18:48:39 2010
New Revision: 73415

Added:
   pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py
Modified:
   pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py
   pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py
Log:
Added some tests for x86

Modified: pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py	Mon Apr  5 18:48:39 2010
@@ -463,6 +463,10 @@
                             log.trace('failed: %s' % (
                                 ', '.join(map(str, fail_args)),))
                         return op.fail_index
+                except UnwindException:
+                    assert op.is_guard()
+                    self._populate_fail_args(op)
+                    raise
                 #verbose = self.verbose
                 assert (result is None) == (op.result is None)
                 if op.result is not None:

Modified: pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py	Mon Apr  5 18:48:39 2010
@@ -32,11 +32,11 @@
 def align_stack_words(words):
     return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1)
 
-JIT_STATE_HEADER = lltype.Struct('JIT_STATE_HEADER',
-                                 ('header', STATE_HEADER),
-                                 ('saved_ints', lltype.Ptr(lltype.GcArray(lltype.Signed))),
-                                 ('saved_floats', lltype.Ptr(lltype.GcArray(lltype.Float))),
-                                 ('saved_refs', lltype.Ptr(lltype.GcArray(lltype.Ptr))))
+JIT_STATE_HEADER = lltype.GcStruct('JIT_STATE_HEADER',
+                                   ('header', STATE_HEADER),
+                                   ('saved_ints', lltype.Ptr(lltype.GcArray(lltype.Signed))),
+                                   ('saved_floats', lltype.Ptr(lltype.GcArray(lltype.Float))),
+                                   ('saved_refs', lltype.Ptr(lltype.GcArray(llmemory.GCREF))))
 
 class MachineCodeBlockWrapper(object):
     MC_DEFAULT_SIZE = 1024*1024
@@ -987,7 +987,7 @@
         loc1 = locs[1]
         if self.cpu.stackless:
             unwinder_addr = self.generate_unwinder_failure(guard_op.descr, guard_op.fail_args, faillocs)
-            stku_type, stku_instance = self.cpu.get_unwind_exception() 
+            stku_type, stku_instance = self.cpu.get_unwind_exception()
             self.mc.CMP(heap(self.cpu.pos_exception()), imm(stku_type))
             self.mc.JE(rel32(unwinder_addr)) # if this is indeed an unwind exception jump to saver code 
         self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
@@ -1228,37 +1228,97 @@
 
     @rgc.no_collect
     def unwind_frame_values(self, bytecode, frame_addr, allregisters):
-        # Okay allocate a frame for us,
+        # Allocate a frame for us,
 
-        # then set the proper values in global_state
+        # XXX set the proper values in global_state 
+        self.fail_ebp = allregisters[16 + ebp.op]
 
-        bytecode = rffi.cast(rffi.UCHARP, bytecode)
         boxes = []
+        kinds = []
+        ints, floats, refs = (0, 0, 0)
+        int_num, float_num, ref_num = (0, 0, 0)
+        int_boxes, float_boxes, ref_boxes = (None, None, None)
+        num = 0
         while 1:
             # decode the next instruction from the bytecode
             code = rffi.cast(lltype.Signed, bytecode[0])
             bytecode = rffi.ptradd(bytecode, 1)
-            kind = code & 3
-            while code > 0x7F:
-                code = rffi.cast(lltype.Signed, bytecode[0])
-                bytecode = rffi.ptradd(bytecode, 1)
-            index = len(boxes)
-            # Now kind contains information at the type of data that will go here
-            if kind != self.DESCR_SPECIAL:
-                kinds.append(kind)
+            if code >= self.CODE_FROMSTACK:
+                if code > 0x7F:
+                    shift = 7
+                    code &= 0x7F
+                    while True:
+                        nextcode = rffi.cast(lltype.Signed, bytecode[0])
+                        bytecode = rffi.ptradd(bytecode, 1)
+                        code |= (nextcode & 0x7F) << shift
+                        shift += 7
+                        if nextcode <= 0x7F:
+                            break
+                # load the value from the stack
+                kind = code & 3
+                code = (code - self.CODE_FROMSTACK) >> 2
+                stackloc = frame_addr + get_ebp_ofs(code)
+                value = rffi.cast(rffi.LONGP, stackloc)[0]
+                kinds.append((kind, True, stackloc))
             else:
-                if code == self.CODE_STOP:
+                kind = code & 3
+                if kind == self.DESCR_SPECIAL:
+                    if code == self.CODE_HOLE:
+                        num += 1
+                        continue
+                    assert code == self.CODE_STOP
                     break
-                assert code == self.CODE_HOLE, "Bad code"
+                code >>= 2
+                kinds.append((kind, False, code))
+
+            if kind == self.DESCR_INT:
+                ints += 1
+            elif kind == self.DESCR_FLOAT:
+                floats += 1
+            elif kind == self.DESCR_REF:
+                refs += 1
 
-        # Now kinds contains the types we need to store
+        # Now kinds contains the types we need to store in the right order
         state_header = lltype.malloc(JIT_STATE_HEADER, zero=True)
         
-        state_header.saved_ints = lltype.malloc(lltype.GcArray(lltype.Signed), len([x for x in kinds if x == self.DESCR_INT]))
-        state_header.saved_floats = lltype.malloc(lltype.GcArray(lltype.Float), len([x for x in kinds if x == self.DESCR_FLOAT]))
-        state_header.saved_floats = lltype.malloc(lltype.GcArray(lltype.Ptr), len([x for x in kinds if x == self.DESCR_REF]))
+        if ints:
+            int_boxes = values_array(lltype.Signed, ints)
+            state_header.saved_ints = int_boxes.ar
+        if floats:
+            float_boxes = values_array(lltype.Float, floats)
+            state_header.saved_floats = float_boxes.ar
+        if refs:
+            ref_boxes = values_array(llmemory.GCREF, refs)
+            state_header.saved_refs = ref_boxes.ar
+
+        value, value_hi = (0, 0)
+
+        for (kind, in_stack, loc) in kinds:
+            if in_stack:
+                value = rffi.cast(rffi.LONGP, loc)[0]
+                if kind == self.DESCR_FLOAT:
+                    value_hi = value
+                    value = rffi.cast(rffi.LONGP, loc - 4)[0]
+            else:
+                if kind == self.DESCR_FLOAT:
+                    value = allregisters[2*loc]
+                    value_hi = allregisters[2*loc+1]
+                else:
+                    value = allregisters[16 + loc]
 
-        
+            if kind == self.DESCR_INT:
+                tgt = int_boxes.get_addr_for_num(int_num)
+                int_num += 1
+            elif kind == self.DESCR_REF:
+                tgt = ref_boxes.get_addr_for_num(ref_num)
+                ref_num += 1
+            elif kind == self.DESCR_FLOAT:
+                tgt = float_boxes.get_addr_for_num(float_num)
+                float_num += 1
+                rffi.cast(rffi.LONGP, tgt)[1] = value_hi
+            rffi.cast(rffi.LONGP, tgt)[0] = value
+
+        return state_header
 
     @rgc.no_collect
     def grab_frame_values(self, bytecode, frame_addr, allregisters):

Added: pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py	Mon Apr  5 18:48:39 2010
@@ -0,0 +1,141 @@
+from pypy.jit.backend.x86.ri386 import *
+from pypy.jit.backend.x86.assembler import Assembler386
+from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
+from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs
+from pypy.jit.backend.x86.test.test_assembler import FakeMC, FakeCPU
+
+def do_unwinder_recovery_func(withfloats=False):
+    import random
+    S = lltype.GcStruct('S')
+
+    def get_random_int():
+        return random.randrange(-10000, 10000)
+    def get_random_ptr():
+        return lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))
+
+    def get_random_float():
+        assert withfloats
+        value = random.random() - 0.5
+        # make sure it fits into 64 bits
+        tmp = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw')
+        rffi.cast(rffi.DOUBLEP, tmp)[0] = value
+        return rffi.cast(rffi.DOUBLEP, tmp)[0], tmp[0], tmp[1]
+
+    # memory locations: 26 integers, 26 pointers, 26 floats
+    # main registers: half of them as signed and the other half as ptrs
+    # xmm registers: all floats, from xmm0 to xmm7
+    # holes: 8
+    locations = []
+    baseloc = 4
+    for i in range(26+26+26):
+        if baseloc < 128:
+            baseloc += random.randrange(2, 20)
+        else:
+            baseloc += random.randrange(2, 1000)
+        locations.append(baseloc)
+    random.shuffle(locations)
+    content = ([('int', locations.pop()) for _ in range(26)] +
+               [('ptr', locations.pop()) for _ in range(26)] +
+               [(['int', 'ptr'][random.randrange(0, 2)], reg)
+                         for reg in [eax, ecx, edx, ebx, esi, edi]])
+    if withfloats:
+        content += ([('float', locations.pop()) for _ in range(26)] +
+                    [('float', reg) for reg in [xmm0, xmm1, xmm2, xmm3,
+                                                xmm4, xmm5, xmm6, xmm7]])
+    for i in range(8):
+        content.append(('hole', None))
+    random.shuffle(content)
+
+    # prepare the expected target arrays, the descr_bytecode,
+    # the 'registers' and the 'stack' arrays according to 'content'
+    xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+9, flavor='raw')
+    registers = rffi.ptradd(xmmregisters, 16)
+    stacklen = baseloc + 10
+    stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw')
+    expected_ints = [] 
+    expected_ptrs = [] 
+    expected_floats = [] 
+
+    def write_in_stack(loc, value):
+        assert loc >= 0
+        ofs = get_ebp_ofs(loc)
+        assert ofs < 0
+        assert (ofs % 4) == 0
+        stack[stacklen + ofs//4] = value
+
+    descr_bytecode = []
+    for i, (kind, loc) in enumerate(content):
+        if kind == 'hole':
+            num = Assembler386.CODE_HOLE
+        else:
+            if kind == 'float':
+                value, lo, hi = get_random_float()
+                expected_floats.append(value)
+                kind = Assembler386.DESCR_FLOAT
+                if isinstance(loc, REG):
+                    xmmregisters[2*loc.op] = lo
+                    xmmregisters[2*loc.op+1] = hi
+                else:
+                    write_in_stack(loc, hi)
+                    write_in_stack(loc+1, lo)
+            else:
+                if kind == 'int':
+                    value = get_random_int()
+                    expected_ints.append(value)
+                    kind = Assembler386.DESCR_INT
+                elif kind == 'ptr':
+                    value = get_random_ptr()
+                    expected_ptrs.append(value)
+                    kind = Assembler386.DESCR_REF
+                    value = rffi.cast(rffi.LONG, value)
+                else:
+                    assert 0, kind
+                if isinstance(loc, REG):
+                    registers[loc.op] = value
+                else:
+                    write_in_stack(loc, value)
+
+            if isinstance(loc, REG):
+                num = kind + 4*loc.op
+            else:
+                num = kind + 4*(8+loc)
+            while num >= 0x80:
+                descr_bytecode.append((num & 0x7F) | 0x80)
+                num >>= 7
+        descr_bytecode.append(num)
+
+    descr_bytecode.append(Assembler386.CODE_STOP)
+    descr_bytecode.append(0xC3)   # fail_index = 0x1C3
+    descr_bytecode.append(0x01)
+    descr_bytecode.append(0x00)
+    descr_bytecode.append(0x00)
+    descr_bytecode.append(0xCC)   # end marker
+    descr_bytes = lltype.malloc(rffi.UCHARP.TO, len(descr_bytecode),
+                                flavor='raw')
+    for i in range(len(descr_bytecode)):
+        assert 0 <= descr_bytecode[i] <= 255
+        descr_bytes[i] = rffi.cast(rffi.UCHAR, descr_bytecode[i])
+    registers[8] = rffi.cast(rffi.LONG, descr_bytes)
+    registers[ebp.op] = rffi.cast(rffi.LONG, stack) + 4*stacklen
+
+    # test
+    assembler = Assembler386(FakeCPU())
+    state_header = assembler.unwinder_recovery_func(registers)
+
+    if state_header.saved_ints:
+        for x,y in zip(state_header.saved_ints, expected_ints):
+            assert x == y
+
+    if state_header.saved_floats:
+        for x,y in zip(state_header.saved_floats, expected_floats):
+            assert x == y
+
+    if state_header.saved_refs:
+        for x,y in zip(state_header.saved_refs, expected_ptrs):
+            assert x == y
+
+def test_unwinder_recovery():
+    do_unwinder_recovery_func()
+
+def test_unwinder_recovery_with_floats():
+    do_unwinder_recovery_func(withfloats=True)

Modified: pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py	(original)
+++ pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py	Mon Apr  5 18:48:39 2010
@@ -13,8 +13,8 @@
 from pypy.translator.stackless.code import yield_current_frame_to_caller
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.annotation.listdef import s_list_of_strings
+from pypy.rpython import llinterp
 from pypy.translator.stackless.transform import StacklessTransformer, FrameTyper
-from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.translator.c import gc
 from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
 from pypy import conftest
@@ -57,3 +57,42 @@
         return x
     res = meta_interp(f, [100])
     assert res == 100
+
+def rtype_stackless_function(fn):
+    t = TranslationContext()
+    t.config.translation.stackless = True
+    annotator = t.buildannotator()
+    annotator.policy.allow_someobjects = False
+
+    s_returnvar = annotator.build_types(fn, [s_list_of_strings])
+    if not isinstance(s_returnvar, annmodel.SomeInteger):
+        raise Exception, "this probably isn't going to work"
+    t.buildrtyper().specialize()
+
+    from pypy.translator.transform import insert_ll_stackcheck
+    insert_ll_stackcheck(t)
+
+#    if conftest.option.view:
+#        t.view()
+    return t
+
+def llinterp_stackless_function(fn, returntranslator=False,
+                                assert_unwind=True):
+    def wrapper(argv):
+        return fn()
+    t = rtype_stackless_function(wrapper)
+    st = StacklessTransformer(t, wrapper, assert_unwind=assert_unwind)
+    st.transform_all()
+    if conftest.option.view:
+        t.view()
+
+    graph = graphof(t, st.slp_entry_point)
+    r_list_of_strings = t.rtyper.getrepr(
+        t.annotator.binding(graph.startblock.inputargs[0]))
+    ll_list = r_list_of_strings.convert_const([''])
+    interp = llinterp.LLInterpreter(t.rtyper)
+    res = interp.eval_graph(graph, [ll_list])
+    if returntranslator:
+        return res, t
+    else:
+        return res



More information about the Pypy-commit mailing list