[pypy-svn] r15451 - in pypy/dist/pypy: annotation rpython/memory rpython/memory/test

cfbolz at codespeak.net cfbolz at codespeak.net
Sun Jul 31 02:19:30 CEST 2005


Author: cfbolz
Date: Sun Jul 31 02:19:27 2005
New Revision: 15451

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/rpython/memory/lladdress.py
   pypy/dist/pypy/rpython/memory/simulator.py
   pypy/dist/pypy/rpython/memory/test/test_address.py
   pypy/dist/pypy/rpython/memory/test/test_simulator.py
Log:
continued  (more or less finished) the memory simulator:
memory access is done by doing:

address.signed[offset] = value
address.signed[offset]

this will check for all sorts of errors.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Sun Jul 31 02:19:27 2005
@@ -618,6 +618,14 @@
     def union((s_addr1, s_addr2)):
         return SomeAddress(is_null=s_addr1.is_null and s_addr2.is_null)
 
+    def sub((s_addr1, s_addr2)):
+        if s_addr1.is_null and s_addr2.is_null:
+            return getbookkeeper().immutablevalue(0)
+        return SomeInteger()
+
+    def is_((s_addr1, s_addr2)):
+        assert False, "comparisons with is not supported by addresses"
+
 class __extend__(pairtype(SomeTypedAddressAccess, SomeTypedAddressAccess)):
     def union((s_taa1, s_taa2)):
         assert s_taa1.type == s_taa2.type
@@ -640,9 +648,3 @@
     def sub((s_addr, s_int)):
         return SomeAddress(is_null=False)
 
-class __extend__(pairtype(SomeAddress, SomeAddress)):
-    def sub((s_addr1, s_addr2)):
-        if s_addr1.is_null and s_addr2.is_null:
-            return getbookkeeper().immutablevalue(0)
-        return SomeInteger()
-        

Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py	(original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py	Sun Jul 31 02:19:27 2005
@@ -1,4 +1,8 @@
+import struct
 from pypy.rpython import lltype
+from pypy.rpython.memory.simulator import MemorySimulator
+from pypy.rpython.rarithmetic import r_uint
+
 
 class Address(object):
     def __new__(cls, intaddress=0):
@@ -14,34 +18,81 @@
     def __init__(self, intaddress=0):
         self.intaddress = intaddress
 
+    def _getintattr(self): #needed to make _accessor easy
+        return self.intaddress
+
     def __add__(self, offset):
         assert isinstance(offset, int)
         return Address(self.intaddress + offset)
 
     def __sub__(self, other):
         if isinstance(other, int):
-            return Address(self.intaddress + offset)
+            return Address(self.intaddress - other)
         else:
             return self.intaddress - other.intaddress
 
     def __cmp__(self, other):
         return cmp(self.intaddress, other.intaddress)
 
-NULL = Address()
+    def __repr__(self):
+        return "<addr: %s>" % self.intaddress
+class _accessor(object):
+    def __init__(self, addr):
+        self.intaddress = addr.intaddress
+    def __getitem__(self, offset):
+        result = simulator.getstruct(self.format,
+                                     self.intaddress + offset * self.size)
+        return self.convert_from(result[0])
+
+    def __setitem__(self, offset, value):
+        simulator.setstruct(self.format, self.intaddress + offset * self.size,
+                            self.convert_to(value))
+           
+class _signed_accessor(_accessor):
+    format = "i"
+    size = struct.calcsize("i")
+    convert_from = int
+    convert_to = int
+
+class _unsigned_accessor(_accessor):
+    format = "I"
+    size = struct.calcsize("I")
+    convert_from = r_uint
+    convert_to = long
+
+class _char_accessor(_accessor):
+    format = "c"
+    size = struct.calcsize("c")
+    convert_from = str
+    convert_to = str
+
+class _address_accessor(_accessor):
+    format = "P"
+    size = struct.calcsize("P")
+    convert_from = Address
+    convert_to = Address._getintattr
+
+Address.signed = property(_signed_accessor)
+Address.unsigned = property(_unsigned_accessor)
+Address.char = property(_char_accessor)
+Address.address = property(_address_accessor)
 
-supported_access_types = {"signed":    lltype.Signed,
-                          "unsigned":  lltype.Unsigned,
-                          "char":      lltype.Char,
-                          "address":   Address,
-                          }
+
+NULL = Address()
+simulator = MemorySimulator()
 
 def raw_malloc(size):
-    pass
+    return Address(simulator.malloc(size))
 
 def raw_free(addr):
-    pass
+    simulator.free(addr.intaddress)
 
 def raw_memcopy(addr1, addr2, size):
     pass
 
 
+supported_access_types = {"signed":    lltype.Signed,
+                          "unsigned":  lltype.Unsigned,
+                          "char":      lltype.Char,
+                          "address":   Address,
+                          }

Modified: pypy/dist/pypy/rpython/memory/simulator.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/simulator.py	(original)
+++ pypy/dist/pypy/rpython/memory/simulator.py	Sun Jul 31 02:19:27 2005
@@ -1,4 +1,5 @@
 import array
+import struct
 
 # all addresses in the simulator are just ints
 
@@ -18,6 +19,8 @@
         self.freed = False
 
     def free(self):
+        if self.freed:
+            raise MemorySimulatorError, "trying to free already freed memory"
         self.freed = True
         self.memory = None
         self.status = None
@@ -44,3 +47,51 @@
         s.fromstring("i" * len(value))
         self.memory[offset:offset + len(value)] = a
         self.status[offset:offset + len(value)] = s
+
+class MemorySimulator(object):
+    def __init__(self):
+        self.blocks = []
+        self.freememoryaddress = 4
+
+    def find_block(self, address):
+        lo = 0
+        hi = len(self.blocks)
+        while lo < hi:
+            mid = (lo + hi) // 2
+            block = self.blocks[mid]
+            if address < block.baseaddress:
+                hi = mid
+            elif address < block.baseaddress + block.size:
+                return block
+            else:
+                lo = mid
+        return self.blocks[mid]
+
+    def malloc(self, size):
+        result = self.freememoryaddress
+        self.blocks.append(MemoryBlock(result, size))
+        self.freememoryaddress += size
+        return result
+
+    def free(self, baseaddress):
+        if baseaddress == 0:
+            raise MemorySimulatorError, "trying to free NULL address"
+        block = self.find_block(baseaddress)
+        if baseaddress != block.baseaddress:
+            raise MemorySimulatorError, "trying to free address not malloc'ed"
+        block.free()
+
+    def getstruct(self, fmt, address):
+        block = self.find_block(address)
+        offset = address - block.baseaddress
+        size = struct.calcsize(fmt)
+        return struct.unpack(fmt, block.getbytes(offset, size))
+
+    def setstruct(self, fmt, address, *types):
+        block = self.find_block(address)
+        offset = address - block.baseaddress
+        block.setbytes(offset, struct.pack(fmt, *types))
+
+    def memcopy(self, address1, address2, size):
+        data = self.getstruct("c" * size, address1)
+        self.setstruct("c" * size, address2, *data)

Modified: pypy/dist/pypy/rpython/memory/test/test_address.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_address.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_address.py	Sun Jul 31 02:19:27 2005
@@ -1,10 +1,12 @@
 import py
+import sys
 
 from pypy.annotation import model as annmodel
 from pypy.translator.annrpython import RPythonAnnotator
 from pypy.objspace.flow import FlowObjSpace
 from pypy.rpython.memory.lladdress import Address, NULL
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
+from pypy.rpython.memory.simulator import MemorySimulatorError
 
 class TestAddressAnnotation(object):
     def test_null(self):
@@ -32,6 +34,7 @@
         a = RPythonAnnotator()
         py.test.raises(AssertionError,
                        a.build_types, f, [annmodel.SomeAddress(is_null=True)])
+        py.test.raises(MemorySimulatorError, f, NULL)
 
     def test_memcopy(self):
         def f(addr1, addr2):
@@ -61,11 +64,12 @@
         s_false.const = False
         s = a.build_types(f, [bool, bool])
         assert isinstance(s, annmodel.SomeAddress)
-        assert not s.is_null 
+        assert not s.is_null
         a = RPythonAnnotator()
         s = a.build_types(f, [s_true, bool])
         assert isinstance(s, annmodel.SomeAddress)
         assert s.is_null
+        assert f(True, False) == NULL
         a = RPythonAnnotator()
         s = a.build_types(f, [s_false, bool])
         assert isinstance(s, annmodel.SomeAddress)
@@ -82,13 +86,16 @@
 
     def test_address_arithmetic(self):
         def f(offset, char):
-            addr = raw_malloc(offset * 2 + 1)
+            addr = raw_malloc(10000)
             same_offset = (addr + offset) - addr
             addr.char[offset] = char
             return (addr + same_offset).char[0]
         a = RPythonAnnotator()
         s = a.build_types(f, [annmodel.SomeInteger(), annmodel.SomeChar()])
         assert isinstance(s, annmodel.SomeChar)
+        assert f(0, "c") == "c"
+        assert f(123, "c") == "c"
+        
 
     def test_address_comparison(self):
         def f(offset):
@@ -104,3 +111,17 @@
     def test_null_is_singleton(self):
         assert Address() is NULL
         assert Address() is Address(0)
+
+    def test_memory_access(self):
+        addr = raw_malloc(1000)
+        addr.signed[0] = -1
+        assert addr.unsigned[0] == sys.maxint * 2 + 1
+        addr.address[0] = addr
+        assert addr.address[0] == addr
+
+    def test_pointer_arithmetic(self):
+        addr = raw_malloc(100)
+        assert addr + 10 - 10 == addr
+        addr.char[10] = "c"
+        assert (addr + 10).char[0] == "c"
+

Modified: pypy/dist/pypy/rpython/memory/test/test_simulator.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_simulator.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_simulator.py	Sun Jul 31 02:19:27 2005
@@ -1,10 +1,57 @@
 import py
-from pypy.rpython.memory.simulator import MemoryBlock
+from pypy.rpython.memory.simulator import *
 
 class TestMemoryBlock(object):
     def test_getsetbyte(self):
-        block = MemoryBlock(1, 1000)
+        block = MemoryBlock(1, 100)
         block.setbytes(1, "hello")
         assert block.getbytes(1, 5) == "hello"
-        
-        
+        #uninitialized memory:
+        py.test.raises(MemorySimulatorError, block.getbytes, 2, 5)
+        #access over block borders:
+        py.test.raises(MemorySimulatorError, block.setbytes, 98, "long string")
+        #accessing freed memory:
+        block.free()
+        py.test.raises(MemorySimulatorError, block.getbytes, 2, 5)
+        #freeing free block:
+        py.test.raises(MemorySimulatorError, block.getbytes, 2, 5)
+
+class TestMemorySimulator(object):
+    def test_find_block(self):
+        simulator = MemorySimulator()
+        for size in [100, 100, 200, 300, 100, 50]:
+            simulator.malloc(size)
+        for address in [12, 99, 110, 190, 210, 310, 420, 450, 510, 630, 710]:
+            block = simulator.find_block(address)
+            assert block.baseaddress <= address < block.baseaddress + block.size
+
+    def test_malloc(self):
+        simulator = MemorySimulator()
+        for size in [2, 4, 8, 16, 32, 64, 128]:
+            baseaddress = simulator.malloc(size)
+            block = simulator.find_block(baseaddress)
+            assert block.size == size
+
+    def test_set_get_struct(self):
+        simulator = MemorySimulator()
+        address = simulator.malloc(100)
+        simulator.setstruct("iic", address, 1, 2, "a")
+        assert simulator.getstruct("iic", address) == (1, 2, "a")
+
+    def test_free(self):
+        simulator = MemorySimulator()
+        addr = simulator.malloc(100)
+        simulator.free(addr)
+        py.test.raises(MemorySimulatorError, simulator.free, addr)
+        py.test.raises(MemorySimulatorError, simulator.free, 0)
+
+    def test_memcopy(self):
+        simulator = MemorySimulator()
+        addr1 = simulator.malloc(1000)
+        addr2 = simulator.malloc(500)
+        simulator.setstruct("iii", addr1, 1, 2, 3)
+        simulator.memcopy(addr1, addr1 + 500, struct.calcsize("iii"))
+        simulator.memcopy(addr1 + 500, addr2, struct.calcsize("iii"))
+        assert simulator.getstruct("iii", addr1) == (1, 2, 3)
+        assert simulator.getstruct("iii", addr1 + 500) == (1, 2, 3)
+        assert simulator.getstruct("iii", addr2) == (1, 2, 3)



More information about the Pypy-commit mailing list