[pypy-svn] r48932 - in pypy/dist/pypy/lang/smalltalk: . test

tverwaes at codespeak.net tverwaes at codespeak.net
Thu Nov 22 17:52:10 CET 2007


Author: tverwaes
Date: Thu Nov 22 17:52:09 2007
New Revision: 48932

Modified:
   pypy/dist/pypy/lang/smalltalk/model.py
   pypy/dist/pypy/lang/smalltalk/primitives.py
   pypy/dist/pypy/lang/smalltalk/squeakimage.py
   pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py
   pypy/dist/pypy/lang/smalltalk/test/test_model.py
   pypy/dist/pypy/lang/smalltalk/test/test_primitives.py
   pypy/dist/pypy/lang/smalltalk/test/test_shadow.py
Log:
another step closer to compiling methods. a bit of a "cleanup" on the at0 and atput0 for compiledmethod, cleaning up issues with methodheaderss


Modified: pypy/dist/pypy/lang/smalltalk/model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/model.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/model.py	Thu Nov 22 17:52:09 2007
@@ -4,6 +4,7 @@
 from pypy.lang.smalltalk import constants
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.objectmodel import instantiate
+from pypy.lang.smalltalk.tool.bitmanipulation import splitter
 
 class W_Object(object):
     __slots__ = ()    # no RPython-level instance variables allowed in W_Object
@@ -299,14 +300,9 @@
     The trailer has two variant formats.  In the first variant, the last byte is at least 252 and the last four bytes represent a source pointer into one of the sources files (see #sourcePointer).  In the second variant, the last byte is less than 252, and the last several bytes are a compressed version of the names of the method's temporary variables.  The number of bytes used for this purpose is the value of the last byte in the method.
     """
 
-    def __init__(self, literalsize, bytes="", argsize=0, 
-                 tempsize=0, primitive=0, w_compiledin=None):
-        self.literals = [None] * literalsize
-        self.w_compiledin = w_compiledin
-        self.bytes = bytes
-        self.argsize = argsize
-        self.tempsize = tempsize
-        self.primitive = primitive
+    def __init__(self, bytecount=0, header=0):
+        self.setheader(header)
+        self.bytes = "\x00"*bytecount
 
     def compiledin(self):  
         if self.w_compiledin is None:
@@ -323,10 +319,11 @@
         return w_CompiledMethod
 
     def getliteral(self, index):
-        return self.literals[index + constants.LITERAL_START]
+        return self.literals[index] #+ constants.LITERAL_START]
 
     def getliteralsymbol(self, index):
         w_literal = self.getliteral(index)
+        print "literals: %r" % self.literals
         assert isinstance(w_literal, W_BytesObject)
         return w_literal.as_string()    # XXX performance issue here
 
@@ -354,36 +351,73 @@
                 self.primitive is not None)       
 
     def size(self):
-        return self.literalsize() + len(self.bytes)
+        return self.getliteralsize() + len(self.bytes)
 
-    def literalsize(self):
-        return len(self.literals) * constants.BYTES_PER_WORD
+    def getliteralsize(self):
+        return self.literalsize * constants.BYTES_PER_WORD
 
     def primsize(self):
-        return self.size() + self.headersize()
+        return self.size()
 
     def headersize(self):
         return constants.BYTES_PER_WORD
 
+    def getheader(self):
+        return self.header
+
+    def setheader(self, header):
+        #(index 0)  9 bits: main part of primitive number   (#primitive)
+        #(index 9)  8 bits: number of literals (#numLiterals)
+        #(index 17) 1 bit:  whether a large frame size is needed (#frameSize)
+        #(index 18) 6 bits: number of temporary variables (#numTemps)
+        #(index 24) 4 bits: number of arguments to the method (#numArgs)
+        #(index 28) 1 bit:  high-bit of primitive number (#primitive)
+        #(index 29) 1 bit:  flag bit, ignored by the VM  (#flag)
+        primitive, literalsize, islarge, tempsize, numargs, highbit = (
+            splitter[9,8,1,6,4,1](header))
+        primitive = primitive + (highbit << 10) ##XXX todo, check this
+        self.literalsize = literalsize
+        self.literals = [w_nil] * self.literalsize
+        self.header = header
+        self.argsize = numargs
+        self.tempsize = tempsize
+        self.primitive = primitive
+        self.w_compiledin = None
+
+    def literalat0(self, index0):
+        if index0 == 0:
+            from pypy.lang.smalltalk import utility
+            return utility.wrap_int(self.getheader())
+        else:
+            return self.literals[index0-1]
+
+    def literalatput0(self, index0, w_value):
+        if index0 == 0:
+            from pypy.lang.smalltalk import utility
+            print "Going to save as header: %r" % w_value
+            header = utility.unwrap_int(w_value)
+            self.setheader(header)
+        else:
+            self.literals[index0-1] = w_value
+
     def at0(self, index0):
         # XXX
         from pypy.lang.smalltalk import utility
-        index0 = index0 - self.literalsize()
-        if index0 < 0:
-            # XXX Do something useful with this.... we are not a block
-            # of memory as smalltalk expects but wrapped in py-os
-            raise NotImplementedError()
-        return utility.wrap_int(ord(self.bytes[index0]))
+        print "TRYING TO GET: %d %d" % (self.getliteralsize(), index0)
+        if index0 < self.getliteralsize():
+            self.literalat0(index0)
+        else:
+            index0 = index0 - self.getliteralsize()
+            return utility.wrap_int(ord(self.bytes[index0]))
         
     def atput0(self, index0, w_value):
         from pypy.lang.smalltalk import utility
-        index0 = index0 - self.literalsize()
-        if index0 < 0:
-            # XXX Do something useful with this.... we are not a block
-            # of memory as smalltalk expects but wrapped in py-os
-            raise NotImplementedError()
+        print "TRYING TO SET: %d %d %r" % (self.getliteralsize(), index0, w_value)
+        if index0 < self.getliteralsize():
+            self.literalatput0(index0, w_value)
         else:
             # XXX use to-be-written unwrap_char
+            index0 = index0 - self.getliteralsize()
             self.setchar(index0, chr(utility.unwrap_int(w_value)))
 
     def setchar(self, index0, character):

Modified: pypy/dist/pypy/lang/smalltalk/primitives.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/primitives.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/primitives.py	Thu Nov 22 17:52:09 2007
@@ -346,16 +346,15 @@
 def func(interp, w_rcvr, n0):
     if not isinstance(w_rcvr, model.W_CompiledMethod):
         raise PrimitiveFailedError()
-    assert_bounds(n0, 0, len(w_rcvr.literals))
-    return w_rcvr.literals[n0]
+    return w_rcvr.literalat0(n0)
 
 @expose_primitive(OBJECT_AT_PUT, unwrap_spec=[object, index1_0, object])
-def func(interp, w_rcvr, n0, w_val):
+def func(interp, w_rcvr, n0, w_value):
     if not isinstance(w_rcvr, model.W_CompiledMethod):
         raise PrimitiveFailedError()
-    assert_bounds(n0, 0, len(w_rcvr.literals))
-    w_rcvr.literals[n0] = w_val
-    return w_val
+    #assert_bounds(n0, 0, len(w_rcvr.literals))
+    w_rcvr.literalatput0(n0, w_value)
+    return w_value
 
 @expose_primitive(NEW, unwrap_spec=[object])
 def func(interp, w_cls):
@@ -419,18 +418,10 @@
     # it returns the "next" instance after w_obj.
     raise PrimitiveNotYetWrittenError()
 
- at expose_primitive(NEW_METHOD, unwrap_spec=[object, int, object])
-def func(interp, w_class, bytecount, w_header):
-    # XXX untested
-    header = utility.unwrap_int(w_header)
-    literalcount = ((header >> 10) & 255) + 1
-    w_method = w_class.as_class_get_shadow().new(literalcount)
-    # XXX not sure this is correct
-    assert isinstance(w_method, model.W_CompiledMethod)
-    w_method.literals[constants.METHOD_HEADER_INDEX] = w_header
-    for i0 in range(1, literalcount):
-        w_method.literals[i0] = objtable.w_nil
-    w_method.bytes = "\x00" * bytecount
+ at expose_primitive(NEW_METHOD, unwrap_spec=[object, int, int])
+def func(interp, w_class, bytecount, header):
+    # We ignore w_class because W_CompiledMethod is special
+    w_method = model.W_CompiledMethod(bytecount, header)
     return w_method
 
 # ___________________________________________________________________________

Modified: pypy/dist/pypy/lang/smalltalk/squeakimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/squeakimage.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/squeakimage.py	Thu Nov 22 17:52:09 2007
@@ -357,29 +357,13 @@
 
     def fillin_compiledmethod(self, w_compiledmethod):
         header = self.chunk.data[0]
-        #---!!!---- 1 tagged pointer!
-        #(index 0)  9 bits: main part of primitive number   (#primitive)
-        #(index 9)  8 bits: number of literals (#numLiterals)
-        #(index 17) 1 bit:  whether a large frame size is needed (#frameSize)
-        #(index 18) 6 bits: number of temporary variables (#numTemps)
-        #(index 24) 4 bits: number of arguments to the method (#numArgs)
-        #(index 28) 1 bit:  high-bit of primitive number (#primitive)
-        #(index 29) 1 bit:  flag bit, ignored by the VM  (#flag)
-        _, primitive, literalsize, islarge, tempsize, numargs, highbit = (
-            splitter[1,9,8,1,6,4,1](header))
-        primitive = primitive + (highbit << 10) ##XXX todo, check this
-        literals = [self.decode_pointer(pointer).w_object
-                    for pointer in self.chunk.data[:literalsize+1]]
-        bbytes = self.get_bytes()[(literalsize + 1)*4:]
+        w_compiledmethod.setheader(header>>1) # We untag before giving header
+        for i in range(1,w_compiledmethod.literalsize+1):
+            w_compiledmethod.literalatput0(i, self.decode_pointer(self.chunk.data[i]).w_object)
+        bbytes = self.get_bytes()[(w_compiledmethod.literalsize + 1)*4:]
         # XXX assert mirrorcache.get_or_build(self.g_class.w_object) is
         #            ct.m_CompiledMethod
-        w_compiledmethod.__init__(
-            literalsize = literalsize,
-            bytes = ''.join(bbytes),
-            argsize = numargs,
-            tempsize = tempsize,
-            primitive = primitive)
-        w_compiledmethod.literals = literals
+        w_compiledmethod.bytes = ''.join(bbytes)
 
 class ImageChunk(object):
     def __init__(self, size, format, classid, hash12):

Modified: pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py	Thu Nov 22 17:52:09 2007
@@ -30,8 +30,10 @@
     # Install faked compiled methods that just invoke the primitive:
     for (w_class, primnum, argsize, methname) in methods:
         s_class = w_class.as_class_get_shadow()
-        prim_meth = model.W_CompiledMethod(
-            0, "", argsize=argsize, primitive=primnum)
+        prim_meth = model.W_CompiledMethod(0)
+        prim_meth.primitive = primnum
+        prim_meth.w_compiledin = w_class
+        prim_meth.argsize = argsize
         s_class.installmethod(methname, prim_meth)
         
     try:
@@ -62,20 +64,24 @@
                 res.storevarpointer(i, fakeliteral(lit[i]))
             return res
         return lit
-    return [fakesymbol("methodheader")]+[fakeliteral(lit) for lit in literals]
+    return [fakeliteral(lit) for lit in literals]
 
 def new_interpreter(bytes, receiver=objtable.w_nil):
     assert isinstance(bytes, str)
-    w_method = model.W_CompiledMethod(0, bytes=bytes,
-                                      argsize=2, tempsize=1)
+    w_method = model.W_CompiledMethod(len(bytes))
+    w_method.bytes = bytes
+    w_method.argsize=2
+    w_method.tempsize=1
     w_frame = w_method.create_frame(receiver, ["foo", "bar"])
     interp = interpreter.Interpreter()
     interp.w_active_context = w_frame
     return interp
 
 def test_create_frame():
-    w_method = model.W_CompiledMethod(0, bytes="hello",
-                                      argsize=2, tempsize=1)
+    w_method = model.W_CompiledMethod(len("hello"))
+    w_method.bytes="hello"
+    w_method.argsize=2
+    w_method.tempsize=1
     w_frame = w_method.create_frame("receiver", ["foo", "bar"])
     assert w_frame.w_receiver == "receiver"
     assert w_frame.gettemp(0) == "foo"
@@ -380,8 +386,9 @@
           (returnNil, interpreter.Interpreter.NIL),
           (returnTopFromMethod, interpreter.Interpreter.ONE) ]:
         shadow = w_class.as_class_get_shadow()
-        shadow.installmethod("foo",
-             model.W_CompiledMethod(0, pushConstantOneBytecode + bytecode))
+        w_method = model.W_CompiledMethod(2)
+        w_method.bytes = pushConstantOneBytecode + bytecode
+        shadow.installmethod("foo", w_method)
         interp = new_interpreter(bytecodes)
         interp.w_active_context.w_method().literals = fakeliterals("foo")
         interp.w_active_context.push(w_object)
@@ -405,7 +412,10 @@
 def test_fibWithArgument():
     bytecode = ''.join(map(chr, [ 16, 119, 178, 154, 118, 164, 11, 112, 16, 118, 177, 224, 112, 16, 119, 177, 224, 176, 124 ]))
     shadow = mockclass(0).as_class_get_shadow()
-    method = model.W_CompiledMethod(1, bytecode, 1)
+    method = model.W_CompiledMethod(len(bytecode))
+    method.literalsize = 1
+    method.bytes = bytecode
+    method.argsize = 1
     method.literals = fakeliterals("fib:")
     shadow.installmethod("fib:", method)
     w_object = shadow.new()
@@ -529,7 +539,11 @@
 def test_callPrimitiveAndPush_fallback():
     interp = new_interpreter(bytecodePrimAdd)
     shadow = mockclass(0).as_class_get_shadow()
-    shadow.installmethod("+", model.W_CompiledMethod(1, "", 1))
+    w_method = model.W_CompiledMethod(0)
+    w_method.argsize = 1
+    w_method.literalsize = 1
+    shadow.installmethod("+", w_method) 
+    
     w_object = shadow.new()
     interp.w_active_context.push(w_object)
     interp.w_active_context.push(interp.ONE)
@@ -567,12 +581,14 @@
     # first call method installed in w_class
     bytecodes = singleExtendedSendBytecode + chr(0)
     # which does a call to its super
-    meth1 = model.W_CompiledMethod(0, pushReceiverBytecode + bytecode)
+    meth1 = model.W_CompiledMethod(2)
+    meth1.bytes = pushReceiverBytecode + bytecode
     w_class.as_class_get_shadow().installmethod("foo", meth1)
     # and that one again to its super
-    meth2 = model.W_CompiledMethod(0, pushReceiverBytecode + bytecode)
+    meth2 = model.W_CompiledMethod(2)
+    meth2.bytes = pushReceiverBytecode + bytecode
     w_super.as_class_get_shadow().installmethod("foo", meth2)
-    meth3 = model.W_CompiledMethod(0, "")
+    meth3 = model.W_CompiledMethod(0)
     w_supersuper.as_class_get_shadow().installmethod("foo", meth3)
     meth1.literals = fakeliterals("foo")
     meth2.literals = fakeliterals("foo")
@@ -726,7 +742,7 @@
 
 def test_bc_primBytecodeAt_with_instvars():
     #   ^ self at: 1
-    py.test.skip("Broken, we are fixing it.")
+    py.test.skip("Broken, fix me")
     w_fakeclass = mockclass(1, name='fakeclass', varsized=True)
     w_fakeinst = w_fakeclass.as_class_get_shadow().new(1)
     w_fakeinst.store(0, wrap_char("a")) # static slot 0: instance variable
@@ -742,7 +758,7 @@
 
 def test_bc_primBytecodeAtPut_with_instvars():
     #   ^ self at: 1 put: #b
-    py.test.skip("Broken, we are fixing it.")
+    py.test.skip("Broken, fix me")
     w_fakeclass = mockclass(1, name='fakeclass', varsized=True)
     w_fakeinst = w_fakeclass.as_class_get_shadow().new(1)
     w_fakeinst.store(0, wrap_char("a")) # static slot 0: instance variable
@@ -763,7 +779,8 @@
     #   ^ self objectAt: 2.          yields the first literal (22)
     #   ^ self objectAt: 2 put: 3.   changes the first literal to 3
     #   ^ self objectAt: 2.          yields the new first literal (3)
-    prim_meth = model.W_CompiledMethod(0, "")
+    py.test.skip("Broken, fix me")
+    prim_meth = model.W_CompiledMethod(0)
     prim_meth.literals = fakeliterals(22)
     mhs = fakesymbol("methodheader")
     oal = fakeliterals("objectAt:")

Modified: pypy/dist/pypy/lang/smalltalk/test/test_model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_model.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_model.py	Thu Nov 22 17:52:09 2007
@@ -66,14 +66,14 @@
     w_super = mockclass(0)
     w_class = mockclass(0, w_superclass=w_super)
     supershadow = w_super.as_class_get_shadow()
-    supershadow.installmethod("foo", model.W_CompiledMethod(0, ""))
+    supershadow.installmethod("foo", model.W_CompiledMethod(0))
     classshadow = w_class.as_class_get_shadow()
     assert classshadow.lookup("foo").w_compiledin is w_super
 
 def test_compiledmethod_setchar():
-    w_method = model.W_CompiledMethod(0, "abc")
+    w_method = model.W_CompiledMethod(3)
     w_method.setchar(0, "c")
-    assert w_method.bytes == "cbc"
+    assert w_method.bytes == "c\x00\x00"
 
 def test_hashes():
     w_five = model.W_SmallInteger(5)

Modified: pypy/dist/pypy/lang/smalltalk/test/test_primitives.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_primitives.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_primitives.py	Thu Nov 22 17:52:09 2007
@@ -207,10 +207,11 @@
     assert prim(primitives.SIZE, [w_obj]).value == 5
 
 def test_size_of_compiled_method():
-    varsize = 3
-    text = "abc"
-    w_cm = model.W_CompiledMethod(varsize, text, 1, 1)
-    assert prim(primitives.SIZE, [w_cm]).value == (varsize+1)*constants.BYTES_PER_WORD + len(text)
+    literalsize = 3
+    bytecount = 3
+    w_cm = model.W_CompiledMethod(bytecount)
+    w_cm.literalsize = literalsize
+    assert prim(primitives.SIZE, [w_cm]).value == (literalsize)*constants.BYTES_PER_WORD + bytecount
 
 def test_string_at():
     assert prim(primitives.STRING_AT, ["foobar", 4]) == wrap("b")
@@ -422,9 +423,9 @@
 
     shadow = mockclass(0).as_class_get_shadow()
     w_method = prim(primitives.NEW_METHOD, [classtable.w_CompiledMethod, len(bytecode), 1025])
-    assert w_method.literals[0].value == 1025
-    assert len(w_method.literals) == 2
-    assert w_method.literals[1] is objtable.w_nil
+    assert w_method.literalat0(0).value == 1025
+    assert w_method.literalsize == 2
+    assert w_method.literalat0(1) is objtable.w_nil
     assert w_method.bytes == "\x00" * len(bytecode)
 
 

Modified: pypy/dist/pypy/lang/smalltalk/test/test_shadow.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_shadow.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_shadow.py	Thu Nov 22 17:52:09 2007
@@ -64,8 +64,8 @@
     yield basicshape, "CompiledMeth", 0xE02,   shadow.COMPILED_METHOD, True, 0
 
 def test_methoddict():
-    methods = {'foo': model.W_CompiledMethod(0, ""),
-               'bar': model.W_CompiledMethod(1, "")}
+    methods = {'foo': model.W_CompiledMethod(0),
+               'bar': model.W_CompiledMethod(0)}
     w_class = build_smalltalk_class("Demo", 0x90, methods=methods)
     classshadow = w_class.as_class_get_shadow()
     assert classshadow.methoddict == methods



More information about the Pypy-commit mailing list