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

arigo at codespeak.net arigo at codespeak.net
Thu Oct 25 20:39:10 CEST 2007


Author: arigo
Date: Thu Oct 25 20:39:10 2007
New Revision: 47982

Modified:
   pypy/dist/pypy/lang/smalltalk/interpreter.py
   pypy/dist/pypy/lang/smalltalk/model.py
   pypy/dist/pypy/lang/smalltalk/shadow.py
   pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py
   pypy/dist/pypy/lang/smalltalk/test/test_miniimage.py
   pypy/dist/pypy/lang/smalltalk/test/test_shadow.py
Log:
(arigo, toon around)
Following some discussion, revert r47962 and go for methoddicts that
contains RPython strings as keys.  This makes it easier to look up
random strings - the interpreter has no way to find the symbol
corresponding to a string in general.

This introduces a performance issue that we think we'll fix with
a ShadowString.


Modified: pypy/dist/pypy/lang/smalltalk/interpreter.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/interpreter.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/interpreter.py	Thu Oct 25 20:39:10 2007
@@ -111,7 +111,7 @@
 
     # send, return bytecodes
     def sendLiteralSelectorBytecode(self, interp):
-        selector = self.w_method().getliteral(self.currentBytecode & 15)
+        selector = self.w_method().getliteralsymbol(self.currentBytecode & 15)
         argcount = ((self.currentBytecode >> 4) & 3) - 1
         self._sendSelfSelector(selector, argcount, interp)
 
@@ -204,7 +204,8 @@
 
     def getExtendedSelectorArgcount(self):
         descriptor = self.getByte()
-        return (self.w_method().getliteral(descriptor & 31)), (descriptor >> 5)
+        return ((self.w_method().getliteralsymbol(descriptor & 31)),
+                (descriptor >> 5))
 
     def singleExtendedSendBytecode(self, interp):
         selector, argcount = self.getExtendedSelectorArgcount()
@@ -216,11 +217,11 @@
         opType = second >> 5
         if opType == 0:
             # selfsend
-            self._sendSelfSelector(self.w_method().getliteral(third),
+            self._sendSelfSelector(self.w_method().getliteralsymbol(third),
                                    second & 31, interp)
         elif opType == 1:
             # supersend
-            self._sendSuperSelector(self.w_method().getliteral(third),
+            self._sendSuperSelector(self.w_method().getliteralsymbol(third),
                                     second & 31, interp)
         elif opType == 2:
             # pushReceiver
@@ -246,7 +247,7 @@
 
     def secondExtendedSendBytecode(self, interp):
         descriptor = self.getByte()
-        selector = self.w_method().getliteral(descriptor & 63)
+        selector = self.w_method().getliteralsymbol(descriptor & 63)
         argcount = descriptor >> 6
         self._sendSelfSelector(selector, argcount, interp)
 

Modified: pypy/dist/pypy/lang/smalltalk/model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/model.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/model.py	Thu Oct 25 20:39:10 2007
@@ -221,6 +221,11 @@
     def getliteral(self, index):
         return self.literals[index + 1] # header of compiledmethod at index 0
 
+    def getliteralsymbol(self, index):
+        w_literal = self.getliteral(index)
+        assert isinstance(w_literal, W_BytesObject)
+        return w_literal.as_string()    # XXX performance issue here
+
     def create_frame(self, receiver, arguments, sender = None):
         assert len(arguments) == self.argsize
         return W_MethodContext(self, receiver, arguments, sender)

Modified: pypy/dist/pypy/lang/smalltalk/shadow.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/shadow.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/shadow.py	Thu Oct 25 20:39:10 2007
@@ -94,8 +94,11 @@
         for i in range(size):
             w_selector = w_methoddict.fetch(constants.METHODDICT_NAMES_INDEX+i)
             if w_selector is not objtable.w_nil:
+                if not isinstance(w_selector, model.W_BytesObject):
+                    raise ClassShadowError("bogus selector in method dict")
+                selector = w_selector.as_string()
                 w_compiledmethod = w_values.fetch(i)
-                self.methoddict[w_selector] = w_compiledmethod
+                self.methoddict[selector] = w_compiledmethod
         # for the rest, we need to reset invalid to False already so
         # that cycles in the superclass and/or metaclass chains don't
         # cause infinite recursion
@@ -169,12 +172,12 @@
         return "<ClassShadow %s>" % (self.name or '?',)
 
     def lookup(self, selector):
-        if selector in self.methoddict:
-            return self.methoddict[selector]
-        elif self.s_superclass is not None:
-            return self.s_superclass.lookup(selector)
-        else:
-            raise MethodNotFound
+        look_in_shadow = self
+        while selector not in look_in_shadow.methoddict:
+            look_in_shadow = look_in_shadow.s_superclass
+            if look_in_shadow is None:
+                raise MethodNotFound
+        return look_in_shadow.methoddict[selector]
 
     def installmethod(self, selector, method):
         "NOT_RPYTHON"     # this is only for testing.

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 Oct 25 20:39:10 2007
@@ -26,8 +26,19 @@
 setup()
 
 
+def fakesymbol(s, _cache={}):
+    try:
+        return _cache[s]
+    except KeyError:
+        result = _cache[s] = objtable.wrap_string(s)
+        return result
+
 def fakeliterals(*literals):
-    return ["methodheader"] + list(literals)
+    lst = ["methodheader"] + list(literals)
+    for i in range(len(lst)):
+        if isinstance(lst[i], str):
+            lst[i] = fakesymbol(lst[i])
+    return lst
 
 def new_interpreter(bytes, receiver=objtable.w_nil):
     assert isinstance(bytes, str)
@@ -108,7 +119,9 @@
     interp.step()
     interp.step()
     interp.step()
-    assert interp.w_active_context.stack == ["a", "b", "c"]
+    assert interp.w_active_context.stack == [fakesymbol("a"),
+                                             fakesymbol("b"),
+                                             fakesymbol("c")]
 
 def test_pushLiteralVariableBytecode(bytecode=pushLiteralVariableBytecode(0)):
     w_association = mockclass(2).as_class_get_shadow().new()

Modified: pypy/dist/pypy/lang/smalltalk/test/test_miniimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_miniimage.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_miniimage.py	Thu Oct 25 20:39:10 2007
@@ -34,29 +34,6 @@
     image = get_image()
     return image.special(constants.SO_FLOAT_CLASS)
 
-# ------ custom lookup implementations --------------------------------
-
-def compiledmethodnamed(w_class, methodname):
-    w_methoddict = w_class.fetch(constants.CLASS_METHODDICT_INDEX)._vars
-    names  = w_methoddict[constants.METHODDICT_NAMES_INDEX:]
-    values = w_methoddict[constants.METHODDICT_VALUES_INDEX]._vars
-    for var in names:
-        if isinstance(var, model.W_BytesObject):
-            if str(var) == str(methodname):
-                return values[names.index(var)]
-    raise shadow.MethodNotFound
-
-def lookup(w_class, methodname):
-    in_class = w_class
-    while in_class != None:
-        try:
-            return compiledmethodnamed(in_class, methodname)
-        except shadow.MethodNotFound:
-            pass
-        in_class = in_class._vars[constants.CLASS_SUPERCLASS_INDEX]
-        if in_class is objtable.w_nil:
-            raise shadow.MethodNotFound
-
 # ------ tests ------------------------------------------
         
 def test_miniimageexists():
@@ -218,15 +195,8 @@
 
     # Should get this from w_object
     w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS)
-    w_method = lookup(w_smallint_class, "abs")
-
-    # XXX
-    # currently still using highlevel lookup directly pointing to
-    # class. Should work using classmirrors when the metaclass of
-    # SmallInt is correctly set
-
-    # s_class = w_object.shadow_of_my_class()
-    # w_method = s_class.lookup("abs")
+    s_class = w_object.shadow_of_my_class()
+    w_method = s_class.lookup("abs")
 
     assert w_method
     w_frame = w_method.create_frame(w_object, [])

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 Oct 25 20:39:10 2007
@@ -18,8 +18,9 @@
     w_methoddict.store(constants.METHODDICT_VALUES_INDEX, w_array)
     positions = range(size)
     random.shuffle(positions)
-    for w_selector, w_compiledmethod in methods.items():
+    for selector, w_compiledmethod in methods.items():
         pos = positions.pop()
+        w_selector = objtable.wrap_string(selector)
         w_methoddict.store(constants.METHODDICT_NAMES_INDEX+pos, w_selector)
         w_array.store(pos, w_compiledmethod)
     #print w_methoddict._vars
@@ -62,8 +63,8 @@
     yield basicshape, "CompiledMeth", 0xE02,   shadow.COMPILED_METHOD, True, 0
 
 def test_methoddict():
-    methods = {objtable.wrap_string('foo'): 'foo_method',
-               objtable.wrap_string('bar'): 'bar_method'}
+    methods = {'foo': 'foo_method',
+               'bar': 'bar_method'}
     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