[pypy-svn] r22508 - in pypy/dist/pypy/rpython: l3interp l3interp/test memory

mwh at codespeak.net mwh at codespeak.net
Mon Jan 23 12:14:44 CET 2006


Author: mwh
Date: Mon Jan 23 12:14:39 2006
New Revision: 22508

Modified:
   pypy/dist/pypy/rpython/l3interp/convertgraph.py
   pypy/dist/pypy/rpython/l3interp/l3interp.py
   pypy/dist/pypy/rpython/l3interp/model.py
   pypy/dist/pypy/rpython/l3interp/test/test_convert.py
   pypy/dist/pypy/rpython/memory/lladdress.py
Log:
(arre, mwh)

A test that getfield of an int on a constant struct can be converted to an
L3 graph that can be l3interped -- and almost nothing else :)


Modified: pypy/dist/pypy/rpython/l3interp/convertgraph.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/convertgraph.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/convertgraph.py	Mon Jan 23 12:14:39 2006
@@ -3,6 +3,7 @@
 from pypy.rpython.l3interp.model import Op
 from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.memory.lladdress import OffsetOf, fakeaddress
 
 
 class LL2L3Converter(object):
@@ -32,6 +33,22 @@
     else:
         return 'ptr'
 
+def getaccesskind(T):
+    assert isinstance(T, lltype.LowLevelType)
+    if isinstance(T, lltype.Primitive):
+        if T == lltype.Float:
+            return 'dbl'
+        if T == lltype.Signed:
+            return 'int'
+        if T == lltype.Char:
+            return 'char'
+        elif T == lltype.Void:
+            raise Exception("accessing a Void value?")
+        else:
+            raise Exception("don't know how to acess %s value"%T)
+    else:
+        return 'ptr'
+
 def convert_block(block, memo):
     if block in memo:
         return memo[block]
@@ -41,7 +58,8 @@
                   'ptr': 0}
     constants = {'int': [],
                  'dbl': [],
-                 'ptr': []}
+                 'ptr': [],
+                 'offset':[]}
     var2stack = {}
 
     def push(v):
@@ -54,11 +72,15 @@
         kind = getkind(v.concretetype)
         if isinstance(v, flowmodel.Constant):
             clist = constants[kind]
+            if kind == 'ptr':
+                value = fakeaddress(v.value)
+            else:
+                value = v.value
             try:
-                res = clist.index(v.value)
+                res = clist.index(value)
             except ValueError:
                 res = len(clist)
-                clist.append(v.value)
+                clist.append(value)
             return res
         else:
             position = var2stack[v]
@@ -87,9 +109,25 @@
         return l3block
 
     for spaceop in block.operations:
-        insns.append(model.very_low_level_opcode[spaceop.opname])
-        for v in spaceop.args:
-            insns.append(get(v))
+        if spaceop.opname == 'getfield':
+            opname = spaceop.opname + '_' + \
+                     getaccesskind(spaceop.result.concretetype)
+            insns.append(model.very_low_level_opcode[opname])
+            v0, v1 = spaceop.args
+            insns.append(get(v0))
+
+            offset = OffsetOf(v0.concretetype, v1.value)
+            clist = constants['offset']
+            try:
+                res = clist.index(offset)
+            except ValueError:
+                res = len(clist)
+                clist.append(offset)
+            insns.append(res)
+        else:
+            insns.append(model.very_low_level_opcode[spaceop.opname])
+            for v in spaceop.args:
+                insns.append(get(v))
         if spaceop.result.concretetype is not lltype.Void:
             push(spaceop.result)
 
@@ -127,5 +165,6 @@
     if constants['int']: l3block.constants_int = constants['int']
     if constants['dbl']: l3block.constants_dbl = constants['dbl']
     if constants['ptr']: l3block.constants_ptr = constants['ptr']
+    if constants['offset']: l3block.constants_offset = constants['offset']
 
     return l3block

Modified: pypy/dist/pypy/rpython/l3interp/l3interp.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/l3interp.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/l3interp.py	Mon Jan 23 12:14:39 2006
@@ -114,6 +114,11 @@
         if op >= 0: return self.block.constants_ptr[op]
         else:       return self.stack_ptr[op]
 
+    def getoffset(self):
+        op = self.nextop()
+        assert op >= 0
+        return self.block.constants_offset[op]
+
     def restorestacks(self):
         del self.stack_int[self.base_int:]
         del self.stack_dbl[self.base_dbl:]
@@ -164,6 +169,11 @@
         else:
             self.stack_int.append(0)
 
+    def op_getfield_int(self):
+        p = self.getptr()
+        o = self.getoffset()
+        self.stack_int.append((p + o).signed[0])
+
     def op_direct_call(self):
         block = self.block
         assert block.called_graphs is not None

Modified: pypy/dist/pypy/rpython/l3interp/model.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/model.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/model.py	Mon Jan 23 12:14:39 2006
@@ -41,7 +41,8 @@
     'getarrayitem', 'getarraysize', 'getarraysubstruct', 'setarrayitem',
 
     #struct operations:
-    'getfield', 'getsubstruct', 'setfield', 
+    'getfield_int', 'getfield_char', 'getfield_dbl', 'getfield_ptr', 
+    'getsubstruct', 'setfield', 
 
     #integer operations:
     'int_abs', 'int_abs_ovf', 'int_add', 'int_add_ovf', 'int_and',
@@ -104,6 +105,7 @@
                               constants_int=None,
                               constants_dbl=None,
                               constants_ptr=None,
+                              constants_offset=None,
                               called_graphs=None):
         self.insns = insns
         self.exit0 = exit0
@@ -111,6 +113,7 @@
         self.constants_int = constants_int
         self.constants_dbl = constants_dbl
         self.constants_ptr = constants_ptr
+        self.constants_offset = constants_offset
         self.called_graphs = called_graphs
 
 class Link(object):

Modified: pypy/dist/pypy/rpython/l3interp/test/test_convert.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/test/test_convert.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/test/test_convert.py	Mon Jan 23 12:14:39 2006
@@ -40,4 +40,24 @@
     assert isinstance(result, l3interp.L3Integer)
     assert result.intval == 1
     
-    
+def test_convert_getfield():
+    class C:
+        def __init__(self, x):
+            self.x = x
+    one = C(1)
+    two = C(2)
+
+    def f(n):
+        if n:
+            return one.x
+        else:
+            return two.x
+    l3graph = l3ify(f, [int])
+    result = l3interp.l3interpret(l3graph, [3], [], [])
+    assert isinstance(result, l3interp.L3Integer)
+    assert result.intval == 1
+
+    result = l3interp.l3interpret(l3graph, [0], [], [])
+    assert isinstance(result, l3interp.L3Integer)
+    assert result.intval == 2
+

Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py	(original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py	Mon Jan 23 12:14:39 2006
@@ -160,3 +160,33 @@
 
 def itemoffsetof(TYPE, n=None):
     pass
+
+class fakeaddress(object):
+    def __init__(self, ob, offset=None):
+        self.ob = ob
+        if offset is None:
+            self.offset = OffsetOf(self.ob._TYPE)
+        else:
+            self.offset = offset
+
+    def __add__(self, other):
+        if not isinstance(other, OffsetOf):
+            return NotImplemented
+        return fakeaddress(self.ob, self.offset + other)
+    
+class _fakeaccessor(object):
+    def __init__(self, addr):
+        self.addr = addr
+    def __getitem__(self, index):
+        assert index == 0
+        ob = self.addr.ob
+        for n in self.addr.offset.fldnames:
+            ob = getattr(ob, n)
+        # XXX will need to do pointers differently!
+        assert lltype.typeOf(ob) == self.TYPE 
+        return ob
+        
+class _signed_fakeaccessor(_fakeaccessor):
+    TYPE = lltype.Signed
+
+fakeaddress.signed = property(_signed_fakeaccessor)



More information about the Pypy-commit mailing list