[pypy-svn] r32091 - in pypy/dist/pypy: jit/codegen jit/codegen/i386 jit/codegen/i386/test jit/timeshifter jit/timeshifter/test jit/tl/test rpython/memory

arigo at codespeak.net arigo at codespeak.net
Sat Sep 9 01:36:55 CEST 2006


Author: arigo
Date: Sat Sep  9 01:36:48 2006
New Revision: 32091

Added:
   pypy/dist/pypy/jit/codegen/graph2rgenop.py   (contents, props changed)
   pypy/dist/pypy/jit/codegen/i386/test/test_genc_tl.py
      - copied, changed from r32080, pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlr.py
   pypy/dist/pypy/jit/codegen/i386/test/test_operation.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/codegen/i386/ri386genop.py
   pypy/dist/pypy/jit/codegen/i386/ri386setup.py
   pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/test/test_tl.py
   pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
   pypy/dist/pypy/jit/tl/test/test_tl.py
   pypy/dist/pypy/jit/tl/test/test_tlr.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
Log:
(pedronis, arigo)

The TL tests pass!

- a bit more about malloc_varsize
- benchmarking at various levels
- graph2rgenop: for testing back-ends, turns a simple ll graph into a
  sequence of rgenop calls that builds the same code
- more tests and more operations for ri386genop



Added: pypy/dist/pypy/jit/codegen/graph2rgenop.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/codegen/graph2rgenop.py	Sat Sep  9 01:36:48 2006
@@ -0,0 +1,77 @@
+"""
+For testing purposes.  Turns *simple enough* low-level graphs
+into machine code by calling the rgenop interface.
+"""
+from pypy.rpython.lltypesystem import lltype
+from pypy.objspace.flow import model as flowmodel
+
+
+def compile_graph(rgenop, graph):
+    FUNC = lltype.FuncType([v.concretetype for v in graph.getargs()],
+                           graph.getreturnvar().concretetype)
+    sigtoken = rgenop.sigToken(FUNC)
+    builder, entrypoint, args_gv = rgenop.newgraph(sigtoken)
+
+    pending_blocks = {graph.startblock: (builder, args_gv)}
+    seen_blocks = {}
+
+    def varkind(v):
+        return rgenop.kindToken(v.concretetype)
+
+    def var2gv(v):
+        if isinstance(v, flowmodel.Variable):
+            return varmap[v]
+        else:
+            return rgenop.genconst(v.value)
+
+    for block in graph.iterblocks():
+        builder, args_gv = pending_blocks.pop(block)
+        assert len(args_gv) == len(block.inputargs)
+        label = builder.enter_next_block(map(varkind, block.inputargs),
+                                         args_gv)
+        seen_blocks[block] = label
+        varmap = dict(zip(block.inputargs, args_gv))
+
+        if not block.exits:
+            [retvar] = block.inputargs
+            builder.finish_and_return(sigtoken, varmap[retvar])
+            continue
+
+        for op in block.operations:
+            # XXX only supports some operations for now
+            if op.opname == 'malloc':
+                token = rgenop.allocToken(op.args[0].value)
+                gv_result = builder.genop_malloc_fixedsize(token)
+            elif op.opname == 'malloc_varsize':
+                token = rgenop.varsizeAllocToken(op.args[0].value)
+                gv_result = builder.genop_malloc_varsize(token,
+                                                         var2gv(op.args[1]))
+            elif op.opname == 'getarrayitem':
+                token = rgenop.arrayToken(op.args[0].concretetype.TO)
+                gv_result = builder.genop_getarrayitem(token,
+                                                       var2gv(op.args[0]),
+                                                       var2gv(op.args[1]))
+            elif op.opname == 'setarrayitem':
+                token = rgenop.arrayToken(op.args[0].concretetype.TO)
+                gv_result = builder.genop_setarrayitem(token,
+                                                       var2gv(op.args[0]),
+                                                       var2gv(op.args[1]),
+                                                       var2gv(op.args[2]))
+            elif len(op.args) == 1:
+                gv_result = builder.genop1(op.opname, var2gv(op.args[0]))
+            elif len(op.args) == 2:
+                gv_result = builder.genop2(op.opname, var2gv(op.args[0]),
+                                                      var2gv(op.args[1]))
+            else:
+                raise NotImplementedError(op.opname)
+            varmap[op.result] = gv_result
+
+        if block.exitswitch is not None:
+            raise NotImplementedError("XXX exitswitch")
+        else:
+            [link] = block.exits
+            args_gv = [var2gv(v) for v in link.args]
+            pending_blocks[link.target] = builder, args_gv
+
+    return rgenop.gencallableconst(sigtoken, "compiled_%s" % (graph.name,),
+                                   entrypoint)

Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386genop.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py	Sat Sep  9 01:36:48 2006
@@ -76,8 +76,10 @@
             return lltype.cast_primitive(T, self.value)
 
     def __repr__(self):
-        return "const=%s" % (imm(self.value).assembler(),)
-        
+        try:
+            return "const=%s" % (imm(self.value).assembler(),)
+        except TypeError:   # from Symbolics
+            return "const=%r" % (self.value,)
 
 
 ##class FnPtrConst(IntConst):
@@ -165,21 +167,29 @@
     def itemaddr(self, base, arraytoken, gv_index):
         # uses ecx
         lengthoffset, startoffset, itemoffset = arraytoken
+        if itemoffset == 1:
+            memSIBx = memSIB8
+        else:
+            memSIBx = memSIB
         if isinstance(gv_index, IntConst):
             startoffset += itemoffset * gv_index.value
-            op = mem(base, startoffset)
+            op = memSIBx(base, None, 0, startoffset)
         elif itemoffset in SIZE2SHIFT:
             self.mc.MOV(ecx, gv_index.operand(self))
-            op = memSIB(base, ecx, SIZE2SHIFT[itemoffset], startoffset)
+            op = memSIBx(base, ecx, SIZE2SHIFT[itemoffset], startoffset)
         else:
             self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset))
-            op = memSIB(base, ecx, 0, startoffset)
+            op = memSIBx(base, ecx, 0, startoffset)
         return op
 
     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
-        # XXX! only works for GcArray(Signed) for now!!
         self.mc.MOV(edx, gv_ptr.operand(self))
         op = self.itemaddr(edx, arraytoken, gv_index)
+        _, _, itemsize = arraytoken
+        if itemsize != WORD:
+            assert itemsize == 1 or itemsize == 2
+            self.mc.MOVZX(eax, op)
+            op = eax
         return self.returnvar(op)
 
     def genop_getarraysize(self, arraytoken, gv_ptr):
@@ -188,17 +198,24 @@
         return self.returnvar(mem(edx, lengthoffset))
 
     def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
-        # XXX! only works for GcArray(Signed) for now!!
         self.mc.MOV(eax, gv_value.operand(self))
         self.mc.MOV(edx, gv_ptr.operand(self))
         destop = self.itemaddr(edx, arraytoken, gv_index)
+        _, _, itemsize = arraytoken
+        if itemsize != WORD:
+            if itemsize == 1:
+                self.mc.MOV(destop, al)
+                return
+            elif itemsize == 2:
+                self.mc.o16()    # followed by the MOV below
+            else:
+                raise AssertionError
         self.mc.MOV(destop, eax)
 
     def genop_malloc_fixedsize(self, size):
         # XXX boehm only, no atomic/non atomic distinction for now
         self.push(imm(size))
-        gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc)
-        self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr)))
+        self.mc.CALL(rel32(gc_malloc_fnaddr()))
         return self.returnvar(eax)
 
     def genop_malloc_varsize(self, varsizealloctoken, gv_size):
@@ -207,8 +224,7 @@
         op_size = self.itemaddr(None, varsizealloctoken, gv_size)
         self.mc.LEA(edx, op_size)
         self.push(edx)
-        gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc)
-        self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr)))
+        self.mc.CALL(rel32(gc_malloc_fnaddr()))
         lengthoffset, _, _ = varsizealloctoken
         self.mc.MOV(ecx, gv_size.operand(self))
         self.mc.MOV(mem(eax, lengthoffset), ecx)
@@ -283,9 +299,12 @@
         self.push(op)
         return res
 
-    def op_int_is_true(self, gv_x):
+    @staticmethod
+    def identity(gv_x):
         return gv_x
 
+    op_int_is_true = identity
+
     def op_int_add(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.ADD(eax, gv_y.operand(self))
@@ -370,6 +389,11 @@
         self.mc.NEG(eax)
         return self.returnvar(eax)
 
+    def op_int_invert(self, gv_x):
+        self.mc.MOV(eax, gv_x.operand(self))
+        self.mc.NOT(eax)
+        return self.returnvar(eax)
+
     def op_int_lshift(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.MOV(ecx, gv_y.operand(self))
@@ -394,6 +418,9 @@
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
+    op_cast_char_to_int = identity
+    op_cast_unichar_to_int = identity
+
     op_ptr_nonzero = op_int_is_true
     op_ptr_iszero  = op_bool_not        # for now
 
@@ -409,6 +436,27 @@
     from pypy.rpython.lltypesystem.lloperation import llop
     return llop.call_boehm_gc_alloc(llmemory.Address, size)
 
+def gc_malloc_fnaddr():
+    """Returns the address of the Boehm 'malloc' function."""
+    if objectmodel.we_are_translated():
+        gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc)
+        return lltype.cast_ptr_to_int(gc_malloc_ptr)
+    else:
+        # <pedronis> don't do this at home
+        try:
+            from ctypes import cast, c_void_p
+            from pypy.rpython.rctypes.tool import util
+            path = util.find_library('gc')
+            if path is None:
+                raise ImportError("Boehm (libgc) not found")
+            boehmlib = util.load_library(path)
+        except ImportError, e:
+            import py
+            py.test.skip(str(e))
+        else:
+            GC_malloc = boehmlib.GC_malloc
+            return cast(GC_malloc, c_void_p).value
+
 # ____________________________________________________________
 
 def remap_stack_layout(builder, outputargs_gv, targetblock):
@@ -536,14 +584,16 @@
     def varsizeAllocToken(T):
         if isinstance(T, lltype.Array):
             return RI386GenOp.arrayToken(T)
-        subfield = T._arrayfld
-        SUBFIELD = getattr(T, subfield)
-        subtoken = RI386GenOp.varsizeAllocToken(SUBFIELD)
-        length_offset, items_offset, item_size = subtoken
-        subfield_offset = llmemory.offsetof(T, subfield)
-        return (subfield_offset+length_offset,
-                subfield_offset+items_offset,
-                item_size)
+        else:
+            # var-sized structs
+            arrayfield = T._arrayfld
+            ARRAYFIELD = getattr(T, arrayfield)
+            arraytoken = RI386GenOp.arrayToken(ARRAYFIELD)
+            length_offset, items_offset, item_size = arraytoken
+            arrayfield_offset = llmemory.offsetof(T, arrayfield)
+            return (arrayfield_offset+length_offset,
+                    arrayfield_offset+items_offset,
+                    item_size)
 
     @staticmethod
     @specialize.memo()    

Modified: pypy/dist/pypy/jit/codegen/i386/ri386setup.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386setup.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386setup.py	Sat Sep  9 01:36:48 2006
@@ -350,6 +350,8 @@
 
 MOVZX = Instruction()
 MOVZX.mode2(REG, MODRM8, ['\x0F\xB6', register(1,8), modrm(2,'b')])
+MOVZX.mode2(REG, MODRM,  ['\x0F\xB7', register(1,8), modrm(2)])
+#                ^^^ but this only reads the 16 lower bits of the source
 MOVZX.as_all_suffixes = 1
 MOVZX.as_alias = "MOVZ"
 
@@ -404,6 +406,9 @@
 BREAKPOINT.mode0(['\xCC'])
 BREAKPOINT.as_alias = "INT3"
 
+o16 = Instruction()      # 16-bits instruction prefix (name from 'nasm')
+o16.mode0(['\x66'])
+
 
 Conditions = {
      'O':  0,

Modified: pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py	Sat Sep  9 01:36:48 2006
@@ -1,8 +1,8 @@
 import os
-from pypy.rpython.objectmodel import specialize
 from pypy.annotation import model as annmodel
 from pypy.jit.timeshifter.test import test_timeshift
 from pypy.jit.codegen.i386.ri386genop import RI386GenOp, IntConst
+from pypy.jit.codegen.i386.test.test_operation import RGenOpPacked
 
 
 class Whatever(object):
@@ -10,30 +10,9 @@
         return True
 
 class I386LLInterpTimeshiftingTestMixin(object):
-    class RGenOp(RI386GenOp):
-        from pypy.jit.codegen.i386.codebuf import LLTypeMachineCodeBlock as MachineCodeBlock
-
-        @staticmethod
-        @specialize.memo()
-        def fieldToken(T, name):
-            return list(T._names).index(name)
-
-        @staticmethod
-        @specialize.memo()
-        def arrayToken(A):
-            return 0, 1, 1
-
-        @staticmethod
-        @specialize.memo()
-        def allocToken(T):
-            return len(T._names)
-
-        varsizeAllocToken = arrayToken
-
-        @staticmethod
-        @specialize.memo()
-        def constFieldName(T, name):
-            return IntConst(list(T._names).index(name))
+    class RGenOp(RGenOpPacked):
+        from pypy.jit.codegen.i386.codebuf import LLTypeMachineCodeBlock \
+                                               as MachineCodeBlock
 
     def timeshift(self, ll_function, values, opt_consts=[], *args, **kwds):
         values = self.timeshift_cached(ll_function, values, *args, **kwds)

Added: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py	Sat Sep  9 01:36:48 2006
@@ -0,0 +1,118 @@
+import py
+from pypy.rpython.objectmodel import specialize
+from pypy.annotation import model as annmodel
+from pypy.rpython.lltypesystem import lltype
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.jit.codegen import graph2rgenop
+from pypy.jit.codegen.i386.ri386genop import RI386GenOp
+from pypy.rpython.memory.lltypelayout import convert_offset_to_int
+from ctypes import cast, c_void_p, CFUNCTYPE, c_int
+
+
+class RGenOpPacked(RI386GenOp):
+    """Like RI386GenOp, but produces concrete offsets in the tokens
+    instead of llmemory.offsets.  These numbers may not agree with
+    your C compiler's.
+    """
+
+    @staticmethod
+    @specialize.memo()
+    def fieldToken(T, name):
+        return convert_offset_to_int(RI386GenOp.fieldToken(T, name))
+
+    @staticmethod
+    @specialize.memo()
+    def arrayToken(A):
+        return tuple(map(convert_offset_to_int, RI386GenOp.arrayToken(A)))
+
+    @staticmethod
+    @specialize.memo()
+    def allocToken(T):
+        return convert_offset_to_int(RI386GenOp.allocToken(T))
+
+    @staticmethod
+    @specialize.memo()
+    def varsizeAllocToken(A):
+        return tuple(map(convert_offset_to_int,
+                         RI386GenOp.varsizeAllocToken(A)))
+
+
+class TestBasic:
+
+    def rgen(self, ll_function, argtypes):
+        t = TranslationContext()
+        t.buildannotator().build_types(ll_function, argtypes)
+        t.buildrtyper().specialize()
+        graph = graphof(t, ll_function)
+        rgenop = RGenOpPacked()
+        self.rgenop = rgenop      # keep this alive!
+        gv_generated = graph2rgenop.compile_graph(rgenop, graph)
+        ctypestypes = [c_int] * len(argtypes)   # for now
+        fp = cast(c_void_p(gv_generated.value), CFUNCTYPE(c_int, *ctypestypes))
+        return fp
+
+    def test_arithmetic(self):
+        for fn in [lambda x, y: x + y,
+                   lambda x, y: x - y,
+                   lambda x, y: x * y,
+                   lambda x, y: x // y,
+                   lambda x, y: x << y,
+                   lambda x, y: x >> y,
+                   lambda x, y: x ^ y,
+                   lambda x, y: x & y,
+                   lambda x, y: x | y,
+                   lambda x, y: -y,
+                   lambda x, y: ~y,
+                   ]:
+            fp = self.rgen(fn, [int, int])
+            assert fp(40, 2) == fn(40, 2)
+
+    def test_comparison(self):
+        for fn in [lambda x, y: int(x <  y),
+                   lambda x, y: int(x <= y),
+                   lambda x, y: int(x == y),
+                   lambda x, y: int(x != y),
+                   lambda x, y: int(x >  y),
+                   lambda x, y: int(x >= y)
+                   ]:
+            fp = self.rgen(fn, [int, int])
+            assert fp(12, 11) == fn(12, 11)
+            assert fp(12, 12) == fn(12, 12)
+            assert fp(12, 13) == fn(12, 13)
+            assert fp(-12, 11) == fn(-12, 11)
+            assert fp(-12, 12) == fn(-12, 12)
+            assert fp(-12, 13) == fn(-12, 13)
+            assert fp(12, -11) == fn(12, -11)
+            assert fp(12, -12) == fn(12, -12)
+            assert fp(12, -13) == fn(12, -13)
+            assert fp(-12, -11) == fn(-12, -11)
+            assert fp(-12, -12) == fn(-12, -12)
+            assert fp(-12, -13) == fn(-12, -13)
+
+    def test_char_array(self):
+        A = lltype.GcArray(lltype.Char)
+        def fn(n):
+            a = lltype.malloc(A, 5)
+            a[4] = 'H'
+            a[3] = 'e'
+            a[2] = 'l'
+            a[1] = 'l'
+            a[0] = 'o'
+            return ord(a[n])
+        fp = self.rgen(fn, [int])
+        for i in range(5):
+            assert fp(i) == fn(i)
+
+    def test_unichar_array(self):
+        A = lltype.GcArray(lltype.UniChar)
+        def fn(n):
+            a = lltype.malloc(A, 5)
+            a[4] = u'H'
+            a[3] = u'e'
+            a[2] = u'l'
+            a[1] = u'l'
+            a[0] = u'o'
+            return ord(a[n])
+        fp = self.rgen(fn, [int])
+        for i in range(5):
+            assert fp(i) == fn(i)

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Sat Sep  9 01:36:48 2006
@@ -38,15 +38,16 @@
     __metaclass__ = cachedtype
     firstsubstructdesc = None
     arrayfielddesc = None
+    alloctoken = None
     varsizealloctoken = None
     
     def __init__(self, RGenOp, TYPE):
         self.TYPE = TYPE
         self.PTRTYPE = lltype.Ptr(TYPE)
-        self.alloctoken = RGenOp.allocToken(self.TYPE)
         self.ptrkind = RGenOp.kindToken(self.PTRTYPE)
         innermostdesc = self
-
+        if not TYPE._is_varsize():
+            self.alloctoken = RGenOp.allocToken(TYPE)
         fielddescs = []
         fielddesc_by_name = {}
         for name in self.TYPE._names:

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Sat Sep  9 01:36:48 2006
@@ -288,7 +288,6 @@
         return r_result.create(hop)
 
     def translate_op_malloc_varsize(self, hop):
-        # XXX no array support for now
         ts = self.timeshifter
         assert isinstance(hop.r_result, RedRepr)
         PTRTYPE = originalconcretetype(hop.s_result)

Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	Sat Sep  9 01:36:48 2006
@@ -732,6 +732,26 @@
                            'setarrayitem': 2, 'getarrayitem': 1,
                            'getarraysize': 1, 'int_mul': 1})
 
+    def test_red_varsized_struct(self):
+         A = lltype.Array(lltype.Signed)
+         S = lltype.GcStruct('S', ('foo', lltype.Signed), ('a', A))
+         def ll_function(x, y, n):
+             s = lltype.malloc(S, 3)
+             s.foo = len(s.a)-1
+             s.a[0] = x
+             s.a[1] = y
+             return s.a[n]*s.foo
+
+         res = self.timeshift(ll_function, [21, -21, 0], [],
+                              policy=P_NOVIRTUAL)
+         assert res == 42
+         self.check_insns(malloc_varsize=1)
+
+         res = self.timeshift(ll_function, [21, -21, 1], [],
+                              policy=P_NOVIRTUAL)
+         assert res == -42
+         self.check_insns(malloc_varsize=1)
+
     def test_red_propagate(self):
         S = lltype.GcStruct('S', ('n', lltype.Signed))
         def ll_function(n, k):

Modified: pypy/dist/pypy/jit/timeshifter/test/test_tl.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tl.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tl.py	Sat Sep  9 01:36:48 2006
@@ -1,6 +1,8 @@
-from pypy.rpython.lltypesystem.rstr import string_repr
+from pypy.rpython.module.support import LLSupport
 from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
 from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC
+from pypy.tool.sourcetools import func_with_new_name
+from pypy.jit.conftest import Benchmark
 
 from pypy.jit.tl import tl
 from pypy.jit.tl.test.test_tl import FACTORIAL_SOURCE
@@ -9,9 +11,22 @@
 class TestTL(TimeshiftingTests):
 
     def test_tl(self):
-        import py; py.test.skip("in-progress")
         code = tl.compile(FACTORIAL_SOURCE)
-        ll_code = string_repr.convert_const(code)
-        res = self.timeshift(tl.interp_without_call, [ll_code, 0, 5], [0, 1],
-                             policy=P_OOPSPEC)
-        assert res == 120
+        bytecode = ','.join([str(ord(c)) for c in code])
+        tl_interp_without_call = func_with_new_name(
+            tl.interp_without_call, "tl_interp_without_call")
+        # to stick attributes on the new function object, not on tl.interp_wit*
+        def build_bytecode(s):
+            result = ''.join([chr(int(t)) for t in s.split(',')])
+            return LLSupport.to_rstr(result)
+        tl_interp_without_call.convert_arguments = [build_bytecode, int, int]
+
+        if Benchmark.ENABLED:
+            n = 2500
+            expected = 0      # far too many powers of 2 to be anything else
+        else:
+            n = 5
+            expected = 120
+        res = self.timeshift(tl_interp_without_call, [bytecode, 0, n],
+                             [0, 1], policy=P_OOPSPEC)
+        assert res == expected

Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tlr.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tlr.py	Sat Sep  9 01:36:48 2006
@@ -1,4 +1,3 @@
-from pypy.rpython.lltypesystem.rstr import string_repr
 from pypy.rpython.module.support import LLSupport
 from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
 from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC

Modified: pypy/dist/pypy/jit/tl/test/test_tl.py
==============================================================================
--- pypy/dist/pypy/jit/tl/test/test_tl.py	(original)
+++ pypy/dist/pypy/jit/tl/test/test_tl.py	Sat Sep  9 01:36:48 2006
@@ -2,6 +2,7 @@
 import operator
 from pypy.jit.tl.tl import interp, compile
 from pypy.jit.tl.opcode import *
+from pypy.jit.conftest import Benchmark
 
 from pypy.translator.translator import TranslationContext
 from pypy.annotation import policy
@@ -255,3 +256,18 @@
     code = compile(FACTORIAL_SOURCE)
     res = interp(code, 0, 6)
     assert res == 720
+
+def test_translate_factorial():
+    # use py.test --benchmark to do the benchmarking
+    code = compile(FACTORIAL_SOURCE)
+    def driver():
+        bench = Benchmark()
+        while 1:
+            res = interp(code, 0, 2500)
+            if bench.stop():
+                break
+        return res
+
+    fn = translate(driver, [])
+    res = fn()
+    assert res == 0       # too many powers of 2 to be anything else

Modified: pypy/dist/pypy/jit/tl/test/test_tlr.py
==============================================================================
--- pypy/dist/pypy/jit/tl/test/test_tlr.py	(original)
+++ pypy/dist/pypy/jit/tl/test/test_tlr.py	Sat Sep  9 01:36:48 2006
@@ -1,7 +1,22 @@
 from pypy.jit.tl import tlr
+from pypy.jit.tl.test.test_tl import translate
+from pypy.jit.conftest import Benchmark
 
 
 def test_square():
     assert tlr.interpret(tlr.SQUARE, 1) == 1
     assert tlr.interpret(tlr.SQUARE, 7) == 49
     assert tlr.interpret(tlr.SQUARE, 9) == 81
+
+def test_translate():
+    def driver():
+        bench = Benchmark()
+        while 1:
+            res = tlr.interpret(tlr.SQUARE, 1764)
+            if bench.stop():
+                break
+        return res
+
+    fn = translate(driver, [])
+    res = fn()
+    assert res == 1764 * 1764

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Sat Sep  9 01:36:48 2006
@@ -5,6 +5,7 @@
 primitive_to_fmt = {lltype.Signed:          "l",
                     lltype.Unsigned:        "L",
                     lltype.Char:            "c",
+                    lltype.UniChar:         "H",     # maybe
                     lltype.Bool:            "B",
                     lltype.Float:           "d",
                     llmemory.Address:       "P",
@@ -103,6 +104,8 @@
         return get_fixed_size(lltype.Signed)
     elif isinstance(offset, llmemory.GCHeaderOffset):
         return sizeof(offset.gcheaderbuilder.HDR)
+    elif isinstance(offset, llmemory.ArrayLengthOffset):
+        return 0
     else:
         raise Exception("unknown offset type %r"%offset)
         



More information about the Pypy-commit mailing list