[pypy-commit] lang-smalltalk default: (cfbolz, lwassermann around): stop using unwrapped strings as values and just

cfbolz noreply at buildbot.pypy.org
Fri Feb 22 11:51:43 CET 2013


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: 
Changeset: r84:235293a3b353
Date: 2013-02-21 15:44 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/235293a3b353/

Log:	(cfbolz, lwassermann around): stop using unwrapped strings as values
	and just compare them by identity, which Squeak guarantees to be
	unique.

	this actually makes the behaviour more correct, because now doing
	nasty stuff like manually changing the symbol won't break method
	dicts.

diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -62,7 +62,7 @@
 SO_SMALLINTEGER_CLASS = 5
 SO_STRING_CLASS = 6
 SO_ARRAY_CLASS = 7
-SO_SMALLTALK = 8 # Deperacted
+SO_SMALLTALK = 8 # Deprecated
 SO_FLOAT_CLASS = 9
 SO_METHODCONTEXT_CLASS = 10
 SO_BLOCKCONTEXT_CLASS = 11
@@ -128,9 +128,25 @@
     "false": SO_FALSE,
     "charactertable": SO_CHARACTER_TABLE_ARRAY,
     "schedulerassociationpointer" : SO_SCHEDULERASSOCIATIONPOINTER,
+    "special_selectors": SO_SPECIAL_SELECTORS_ARRAY,
     "smalltalkdict" : SO_SMALLTALK,
 }
 
 LONG_BIT = 32
 TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1
 TAGGED_MININT = -2 ** (LONG_BIT - 2)
+
+
+# Entries into SO_SPECIAL_SELECTORS_ARRAY:
+#(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
+
+
+SPECIAL_SELECTORS = ['+', '-', '<', '>', '<=', '>=', '=', '~=', '*', '/', '\\\\',
+                     '@', 'bitShift:', '//', 'bitAnd:', 'bitOr:', 'at:',
+                     'at:put:', 'size', 'next', 'nextPut:', 'atEnd', '==',
+                     'class', 'blockCopy:', 'value', 'value:', 'do:', 'new',
+                     'new:', 'x', 'y']
+
+def find_selectorindex(selector):
+    return SPECIAL_SELECTORS.index(selector) * 2
+find_selectorindex._annspecialcase_ = "specialize:memo"
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -115,13 +115,14 @@
         # else that the user put in a class in an 'at:' method.
         # The rule of thumb is that primitives with only int and float
         # in their unwrap_spec are safe.
+        # XXX move next line out of callPrimitive?
         func = primitives.prim_table[primitive]
         try:
             func(interp, argcount)
             return
         except primitives.PrimitiveFailedError:
             pass
-        self._sendSelfSelector(selector, argcount, interp)
+        self._sendSelfSelectorSpecial(selector, argcount, interp)
     return callPrimitive
 
 # ___________________________________________________________________________
@@ -194,31 +195,31 @@
 
     # send, return bytecodes
     def sendLiteralSelectorBytecode(self, interp):
-        selector = self.method().getliteralsymbol(self.currentBytecode & 15)
+        w_selector = self.method().getliteral(self.currentBytecode & 15)
         argcount = ((self.currentBytecode >> 4) & 3) - 1
-        self._sendSelfSelector(selector, argcount, interp)
+        self._sendSelfSelector(w_selector, argcount, interp)
 
-    def _sendSelfSelector(self, selector, argcount, interp):
+    def _sendSelfSelector(self, w_selector, argcount, interp):
         receiver = self.peek(argcount)
-        self._sendSelector(selector, argcount, interp,
+        self._sendSelector(w_selector, argcount, interp,
                            receiver, receiver.shadow_of_my_class(self.space))
 
-    def _sendSuperSelector(self, selector, argcount, interp):
+    def _sendSuperSelector(self, w_selector, argcount, interp):
         w_compiledin = self.method().w_compiledin
         assert isinstance(w_compiledin, model.W_PointersObject)
         s_compiledin = w_compiledin.as_class_get_shadow(self.space)
-        self._sendSelector(selector, argcount, interp, self.w_receiver(),
+        self._sendSelector(w_selector, argcount, interp, self.w_receiver(),
                            s_compiledin.s_superclass())
 
-    def _sendSelector(self, selector, argcount, interp,
+    def _sendSelector(self, w_selector, argcount, interp,
                       receiver, receiverclassshadow):
         if interp.should_trace():
             print "%sSending selector %r to %r with: %r" % (
-                interp._last_indent, selector, receiver,
+                interp._last_indent, w_selector.as_string(), receiver,
                 [self.peek(argcount-1-i) for i in range(argcount)])
             pass
         assert argcount >= 0
-        method = receiverclassshadow.lookup(selector)
+        method = receiverclassshadow.lookup(w_selector)
         # XXX catch MethodNotFound here and send doesNotUnderstand:
         # AK shouln't that be done in lookup itself, please check what spec says about DNU in case of super sends.
         if method.primitive:
@@ -242,7 +243,7 @@
                     return
                 except primitives.PrimitiveFailedError:
                     if interp.should_trace(True):
-                        print "PRIMITIVE FAILED: %d %s" % (method.primitive, selector,)
+                        print "PRIMITIVE FAILED: %d %s" % (method.primitive, w_selector.as_string(),)
                     pass # ignore this error and fall back to the Smalltalk version
         arguments = self.pop_and_return_n(argcount)
         frame = method.create_frame(self.space, receiver, arguments,
@@ -317,12 +318,12 @@
 
     def getExtendedSelectorArgcount(self):
         descriptor = self.getbytecode()
-        return ((self.method().getliteralsymbol(descriptor & 31)),
+        return ((self.method().getliteral(descriptor & 31)),
                 (descriptor >> 5))
 
     def singleExtendedSendBytecode(self, interp):
-        selector, argcount = self.getExtendedSelectorArgcount()
-        self._sendSelfSelector(selector, argcount, interp)
+        w_selector, argcount = self.getExtendedSelectorArgcount()
+        self._sendSelfSelector(w_selector, argcount, interp)
 
     def doubleExtendedDoAnythingBytecode(self, interp):
         second = self.getbytecode()
@@ -330,11 +331,11 @@
         opType = second >> 5
         if opType == 0:
             # selfsend
-            self._sendSelfSelector(self.method().getliteralsymbol(third),
+            self._sendSelfSelector(self.method().getliteral(third),
                                    second & 31, interp)
         elif opType == 1:
             # supersend
-            self._sendSuperSelector(self.method().getliteralsymbol(third),
+            self._sendSuperSelector(self.method().getliteral(third),
                                     second & 31, interp)
         elif opType == 2:
             # pushReceiver
@@ -357,14 +358,14 @@
             association.store_value(self.top())
 
     def singleExtendedSuperBytecode(self, interp):
-        selector, argcount = self.getExtendedSelectorArgcount()
-        self._sendSuperSelector(selector, argcount, interp)
+        w_selector, argcount = self.getExtendedSelectorArgcount()
+        self._sendSuperSelector(w_selector, argcount, interp)
 
     def secondExtendedSendBytecode(self, interp):
         descriptor = self.getbytecode()
-        selector = self.method().getliteralsymbol(descriptor & 63)
+        w_selector = self.method().getliteral(descriptor & 63)
         argcount = descriptor >> 6
-        self._sendSelfSelector(selector, argcount, interp)
+        self._sendSelfSelector(w_selector, argcount, interp)
 
     def popStackBytecode(self, interp):
         self.pop()
@@ -479,27 +480,32 @@
     bytecodePrimBitAnd = make_call_primitive_bytecode(primitives.BIT_AND, "bitAnd:", 1)
     bytecodePrimBitOr = make_call_primitive_bytecode(primitives.BIT_OR, "bitOr:", 1)
 
+    @objectmodel.specialize.arg(1)
+    def _sendSelfSelectorSpecial(self, selector, numargs, interp):
+        w_selector = self.space.get_special_selector(selector)
+        return self._sendSelfSelector(w_selector, numargs, interp)
+
     def bytecodePrimAt(self, interp):
         # n.b.: depending on the type of the receiver, this may invoke
         # primitives.AT, primitives.STRING_AT, or something else for all
-        # I know.  
-        self._sendSelfSelector("at:", 1, interp)
+        # I know.
+        self._sendSelfSelectorSpecial("at:", 1, interp)
 
     def bytecodePrimAtPut(self, interp):
         # n.b. as above
-        self._sendSelfSelector("at:put:", 2, interp)
+        self._sendSelfSelectorSpecial("at:put:", 2, interp)
 
     def bytecodePrimSize(self, interp):
-        self._sendSelfSelector("size", 0, interp)
+        self._sendSelfSelectorSpecial("size", 0, interp)
 
     def bytecodePrimNext(self, interp):
-        self._sendSelfSelector("next", 0, interp)
+        self._sendSelfSelectorSpecial("next", 0, interp)
 
     def bytecodePrimNextPut(self, interp):
-        self._sendSelfSelector("nextPut:", 1, interp)
+        self._sendSelfSelectorSpecial("nextPut:", 1, interp)
 
     def bytecodePrimAtEnd(self, interp):
-        self._sendSelfSelector("atEnd", 0, interp)
+        self._sendSelfSelectorSpecial("atEnd", 0, interp)
 
     def bytecodePrimEquivalent(self, interp):
         # short-circuit: classes cannot override the '==' method,
@@ -517,19 +523,19 @@
     bytecodePrimValueWithArg = make_call_primitive_bytecode(primitives.VALUE, "value:", 1)
 
     def bytecodePrimDo(self, interp):
-        self._sendSelfSelector("do:", 1, interp)
+        self._sendSelfSelectorSpecial("do:", 1, interp)
 
     def bytecodePrimNew(self, interp):
-        self._sendSelfSelector("new", 0, interp)
+        self._sendSelfSelectorSpecial("new", 0, interp)
 
     def bytecodePrimNewWithArg(self, interp):
-        self._sendSelfSelector("new:", 1, interp)
+        self._sendSelfSelectorSpecial("new:", 1, interp)
 
     def bytecodePrimPointX(self, interp):
-        self._sendSelfSelector("x", 0, interp)
+        self._sendSelfSelectorSpecial("x", 0, interp)
 
     def bytecodePrimPointY(self, interp):
-        self._sendSelfSelector("y", 0, interp)
+        self._sendSelfSelectorSpecial("y", 0, interp)
 
 BYTECODE_RANGES = [
             (  0,  15, "pushReceiverVariableBytecode"),
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -1,6 +1,6 @@
 from spyvm import constants, model, shadow, wrapper
 from spyvm.error import UnwrappingError, WrappingError
-from rpython.rlib.objectmodel import instantiate
+from rpython.rlib.objectmodel import instantiate, specialize
 from rpython.rlib.rarithmetic import intmask, r_uint
 
 class ObjSpace(object):
@@ -147,8 +147,11 @@
         self.w_zero = model.W_SmallInteger(0)
         self.w_one = model.W_SmallInteger(1)
         self.w_two = model.W_SmallInteger(2)
+        w_special_selectors = model.W_PointersObject(
+            self.classtable['w_Array'], len(constants.SPECIAL_SELECTORS) * 2)
+        self.w_special_selectors = w_special_selectors
+
         self.objtable = {}
-
         for name in constants.objects_in_special_object_table:
             name = "w_" + name
             try:
@@ -156,6 +159,11 @@
             except KeyError, e:
                 self.objtable[name] = None
 
+    @specialize.arg(1)
+    def get_special_selector(self, selector):
+        i0 = constants.find_selectorindex(selector)
+        return self.w_special_selectors.at0(self, i0)
+
     # methods for wrapping and unwrapping stuff
 
     def wrap_int(self, val):
@@ -255,7 +263,7 @@
     def unwrap_array(self, w_array):
         # Check that our argument has pointers format and the class:
         if not w_array.getclass(self).is_same_object(self.w_Array):
-            raise PrimitiveFailedError()
+            raise UnwrappingError()
         assert isinstance(w_array, model.W_PointersObject)
         
         return [w_array.at0(self, i) for i in range(w_array.size())]
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -856,10 +856,10 @@
     raise PrimitiveFailedError()
 
 @expose_primitive(PERFORM_WITH_ARGS,
-                  unwrap_spec=[object, str, object],
+                  unwrap_spec=[object, object, object],
                   no_result=True)
-def func(interp, w_rcvr, sel, w_args):
-    w_method = w_rcvr.shadow_of_my_class(interp.space).lookup(sel)
+def func(interp, w_rcvr, w_sel, w_args):
+    w_method = w_rcvr.shadow_of_my_class(interp.space).lookup(w_sel)
     assert w_method
 
     w_frame = w_method.create_frame(interp.space, w_rcvr,
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -232,15 +232,15 @@
     def __repr__(self):
         return "<ClassShadow %s>" % (self.name or '?',)
 
-    def lookup(self, selector):
+    def lookup(self, w_selector):
         look_in_shadow = self
         while look_in_shadow is not None:
             try:
-                w_method = look_in_shadow.s_methoddict().methoddict[selector]
+                w_method = look_in_shadow.s_methoddict().methoddict[w_selector]
                 return w_method
             except KeyError, e:
                 look_in_shadow = look_in_shadow.s_superclass()
-        raise MethodNotFound(self, selector)
+        raise MethodNotFound(self, w_selector)
 
     def initialize_methoddict(self):
         "NOT_RPYTHON"     # this is only for testing.
@@ -249,10 +249,11 @@
             self.w_methoddict._store(1, model.W_PointersObject(None, 0))
             self.s_methoddict().invalid = False
 
-    def installmethod(self, selector, w_method):
+    def installmethod(self, w_selector, w_method):
         "NOT_RPYTHON"     # this is only for testing.
+        assert not isinstance(w_selector, str)
         self.initialize_methoddict()
-        self.s_methoddict().methoddict[selector] = w_method
+        self.s_methoddict().methoddict[w_selector] = w_method
         if isinstance(w_method, model.W_CompiledMethod):
             method = w_method.as_compiledmethod_get_shadow(self.space)
             method.w_compiledin = self.w_self()
@@ -276,12 +277,12 @@
             if not w_selector.is_same_object(self.space.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)
                 if not isinstance(w_compiledmethod, model.W_CompiledMethod):
                     raise ClassShadowError("the methoddict must contain "
                                            "CompiledMethods only for now")
-                self.methoddict[selector] = w_compiledmethod
+                self.methoddict[w_selector] = w_compiledmethod
+                selector = w_selector.as_string()
                 w_compiledmethod._likely_methodname = selector
 
 
@@ -738,7 +739,8 @@
 class CompiledMethodShadow(object):
     _immutable_fields_ = ["_w_self", "bytecode",
                           "literals[*]", "bytecodeoffset",
-                          "literalsize", "tempsize", "w_compiledin"]
+                          "literalsize", "tempsize", "primitive",
+                          "w_compiledin"]
 
     def __init__(self, w_compiledmethod):
         self._w_self = w_compiledmethod
@@ -747,6 +749,7 @@
         self.bytecodeoffset = w_compiledmethod.bytecodeoffset()
         self.literalsize = w_compiledmethod.getliteralsize()
         self.tempsize = w_compiledmethod.gettempsize()
+        self.primitive = w_compiledmethod.primitive
 
         self.w_compiledin = None
         if self.literals:
diff --git a/spyvm/test/jit.py b/spyvm/test/jit.py
--- a/spyvm/test/jit.py
+++ b/spyvm/test/jit.py
@@ -77,4 +77,4 @@
         def interp_w():
             interp.interpret()
 
-        self.meta_interp(interp_w, [], listcomp=True, listops=True, backendopt=True)
\ No newline at end of file
+        self.meta_interp(interp_w, [], listcomp=True, listops=True, backendopt=True)
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -1,6 +1,6 @@
 import py
 from spyvm import model, interpreter, primitives, shadow
-from spyvm import objspace, wrapper
+from spyvm import objspace, wrapper, constants
 
 mockclass = objspace.bootstrap_class
 
@@ -25,7 +25,7 @@
             globals()[name] = make_getter(entry)
 setup()
 
-def run_with_faked_methods(methods, func, active_context=None):
+def run_with_faked_primitive_methods(methods, func, active_context=None):
 
     # Install faked compiled methods that just invoke the primitive:
     for (w_class, primnum, argsize, methname) in methods:
@@ -33,8 +33,17 @@
         prim_meth = model.W_CompiledMethod(0)
         prim_meth.primitive = primnum
         prim_meth.argsize = argsize
-        s_class.installmethod(methname, prim_meth)
-        
+        symbol = fakesymbol(methname)
+        # somewhat evil:
+        try:
+            index = constants.find_selectorindex(methname)
+        except ValueError:
+            pass
+        else:
+            space.w_special_selectors.atput0(space, index, symbol)
+            assert space.get_special_selector(methname) is symbol
+        s_class.installmethod(symbol, prim_meth)
+
         assert space.w_nil._shadow is None
     try:
         func(active_context) if active_context else func()
@@ -43,7 +52,7 @@
         assert space.w_nil._shadow is None
         for (w_class, _, _, methname) in methods:
             s_class = w_class.as_class_get_shadow(space)
-            del s_class.s_methoddict().methoddict[methname]
+            del s_class.s_methoddict().methoddict[fakesymbol(methname)]
 
 def fakesymbol(s, _cache={}):
     try:
@@ -349,7 +358,7 @@
                             w_metaclass=w_fakeclassclass)
     interp = new_interpreter(bytecodePrimNew)
     interp.s_active_context().push(w_fakeclass)
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[w_fakeclassclass, primitives.NEW, 0, "new"]],
         interp.step,
         interp.s_active_context())
@@ -365,7 +374,7 @@
     interp = new_interpreter(bytecodePrimNewWithArg)
     interp.s_active_context().push(w_fakeclass)
     interp.s_active_context().push(space.w_two)
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[w_fakeclassclass, primitives.NEW_WITH_ARG, 1, "new:"]],
         interp.step,
         interp.s_active_context())
@@ -379,7 +388,7 @@
     w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(5)
     interp = new_interpreter(bytecodePrimSize)
     interp.s_active_context().push(w_fakeinst)
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[w_fakeclass, primitives.SIZE, 0, "size"]],
         interp.step,
         interp.s_active_context())
@@ -399,16 +408,18 @@
         shadow = w_class.as_class_get_shadow(space)
         w_method = model.W_CompiledMethod(2)
         w_method.bytes = pushConstantOneBytecode + bytecode
-        shadow.installmethod("foo", w_method)
+        literals = fakeliterals(space, "foo")
+        w_foo = literals[0]
+        shadow.installmethod(w_foo, w_method)
         interp = new_interpreter(bytecodes)
-        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "foo"))
+        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
         interp.s_active_context().push(w_object)
         callerContext = interp.w_active_context()
         interp.step(interp.s_active_context())
         assert interp.s_active_context().w_sender() == callerContext
         assert interp.s_active_context().stack() == []
         assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver().is_same_object(w_object)
-        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method().is_same_object(shadow.s_methoddict().methoddict["foo"])
+        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method().is_same_object(shadow.s_methoddict().methoddict[w_foo])
         assert callerContext.as_context_get_shadow(space).stack() == []
         interp.step(interp.s_active_context())
         interp.step(interp.s_active_context())
@@ -428,11 +439,12 @@
     method.bytes = bytecode
     method.argsize = 1
     method.tempsize = 1
-    method.setliterals(fakeliterals(space, "fib:"))
-    shadow.installmethod("fib:", method)
+    literals = fakeliterals(space, "fib:")
+    method.setliterals(literals)
+    shadow.installmethod(literals[0], method)
     w_object = shadow.new()
     interp = new_interpreter(sendLiteralSelectorBytecode(16) + returnTopFromMethod)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "fib:"))
+    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
     interp.s_active_context().push(w_object)
     interp.s_active_context().push(space.wrap_int(8))
     result = interp.interpret()
@@ -442,7 +454,7 @@
 
     def test():
         interp = new_interpreter(sendLiteralSelectorBytecode(1 + 16))
-        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "foo", "sub"))
+        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "foo", "-"))
         interp.s_active_context().push(space.wrap_int(50))
         interp.s_active_context().push(space.wrap_int(8))
         callerContext = interp.w_active_context()
@@ -452,9 +464,9 @@
         w_result = interp.s_active_context().pop()
         assert space.unwrap_int(w_result) == 42
         
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_SmallInteger, primitives.SUBTRACT,
-          1, "sub"]],
+          1, "-"]],
         test)
 
 def test_makePoint():
@@ -568,13 +580,16 @@
     w_method.argsize = 1
     w_method.tempsize = 1
     w_method.literalsize = 1
-    shadow.installmethod("+", w_method) 
-    
+    w_symbol = fakesymbol("+")
+    shadow.installmethod(w_symbol, w_method)
+    # slightly evil
+    space.w_special_selectors.atput0(space, constants.find_selectorindex("+"), w_symbol)
+
     w_object = shadow.new()
     interp.s_active_context().push(w_object)
     interp.s_active_context().push(space.w_one)
     interp.step(interp.s_active_context())
-    assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == shadow.s_methoddict().methoddict["+"]
+    assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == shadow.s_methoddict().methoddict[w_symbol]
     assert interp.s_active_context().w_receiver() is w_object
     assert interp.w_active_context().as_methodcontext_get_shadow(space).gettemp(0).is_same_object(space.w_one)
     assert interp.s_active_context().stack() == []
@@ -609,17 +624,19 @@
     # which does a call to its super
     meth1 = model.W_CompiledMethod(2)
     meth1.bytes = pushReceiverBytecode + bytecode
-    meth1.setliterals(fakeliterals(space, "foo"))
-    w_class.as_class_get_shadow(space).installmethod("foo", meth1)
+    literals = fakeliterals(space, "foo")
+    foo = literals[0]
+    meth1.setliterals(literals)
+    w_class.as_class_get_shadow(space).installmethod(foo, meth1)
     # and that one again to its super
     meth2 = model.W_CompiledMethod(2)
     meth2.bytes = pushReceiverBytecode + bytecode
-    meth2.setliterals(fakeliterals(space, "foo"))
-    w_super.as_class_get_shadow(space).installmethod("foo", meth2)
+    meth2.setliterals(fakeliterals(space, foo))
+    w_super.as_class_get_shadow(space).installmethod(foo, meth2)
     meth3 = model.W_CompiledMethod(0)
-    w_supersuper.as_class_get_shadow(space).installmethod("foo", meth3)
+    w_supersuper.as_class_get_shadow(space).installmethod(foo, meth3)
     interp = new_interpreter(bytecodes)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "foo"))
+    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
     interp.s_active_context().push(w_object)
     interp.step(interp.s_active_context())
     for w_specificclass in [w_super, w_supersuper]:
@@ -629,7 +646,7 @@
         assert interp.s_active_context().w_sender() == callerContext
         assert interp.s_active_context().stack() == []
         assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver() == w_object
-        meth = w_specificclass.as_class_get_shadow(space).s_methoddict().methoddict["foo"]
+        meth = w_specificclass.as_class_get_shadow(space).s_methoddict().methoddict[foo]
         assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == meth
         assert callerContext.as_context_get_shadow(space).stack() == []
 
@@ -703,7 +720,7 @@
             [ 137, 119, 200, 164, 6, 105, 104, 16, 17,
               176, 125, 33, 34, 240, 124 ],
             fakeliterals(space, "value:value:", space.wrap_int(3), space.wrap_int(4))).value == 7
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_BlockContext, primitives.VALUE,
           2, "value:value:"]],
         test)
@@ -741,7 +758,7 @@
               125, 33, 224, 124 ],
             fakeliterals(space, "valueWithArguments:",
                          [3, 2])).value == 1
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_BlockContext, primitives.VALUE_WITH_ARGS,
           1, "valueWithArguments:"]],
         test)
@@ -752,7 +769,7 @@
         assert interpret_bc(
             [ 32, 118, 192, 124],
             fakeliterals(space, "a")) == space.wrap_char("a")
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_String, primitives.STRING_AT, 1, "at:"]],
         test)
     
@@ -762,7 +779,7 @@
         assert interpret_bc(
             [ 32, 118, 33, 193, 124 ],
             fakeliterals(space, "a", space.wrap_char("b"))) == space.wrap_char("b")
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_String, primitives.STRING_AT_PUT, 2, "at:put:"]],
         test)
 
@@ -777,7 +794,7 @@
             [112, 118, 192, 124],
             fakeliterals(space, ),
             receiver=w_fakeinst)) == "b"
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[w_fakeclass, primitives.AT, 1, "at:"]],
         test)
 
@@ -794,7 +811,7 @@
             receiver=w_fakeinst)) == "b"
         assert space.unwrap_char(w_fakeinst.fetch(space, 0)) == "a"
         assert space.unwrap_char(w_fakeinst.fetch(space, 1)) == "b"
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[w_fakeclass, primitives.AT_PUT, 2, "at:put:"]],
         test)
 
@@ -816,7 +833,7 @@
             [112, 119, 33, 240, 124], oalp, receiver=prim_meth).value == 3
         assert interpret_bc(
             [112, 119, 224, 124], oal, receiver=prim_meth).value == 3
-    run_with_faked_methods(
+    run_with_faked_primitive_methods(
         [[space.w_CompiledMethod, primitives.OBJECT_AT, 1, "objectAt:"],
          [space.w_CompiledMethod, primitives.OBJECT_AT_PUT, 2, "objectAt:put:"]],
         test)
diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py
--- a/spyvm/test/test_miniimage.py
+++ b/spyvm/test/test_miniimage.py
@@ -17,9 +17,23 @@
     module.reader = open_miniimage(space)
     reader.initialize()
     module.image = squeakimage.SqueakImage()
-    module.image.from_reader(space, get_reader())
+    module.image.from_reader(space, reader)
     module.space = space
-    
+
+def find_symbol(name):
+    w_dnu = image.special(constants.SO_DOES_NOT_UNDERSTAND)
+    assert str(w_dnu) == "doesNotUnderstand:"
+    w_Symbol = w_dnu.getclass(space)
+    for chunk in reader.chunklist:
+        w_obj = chunk.g_object.w_object
+        if not isinstance(w_obj, model.W_BytesObject):
+            continue
+        if not w_obj.getclass(space).is_same_object(w_Symbol):
+            continue
+        if w_obj.as_string() == name:
+            return w_obj
+    return perform(space.wrap_string(name), "asSymbol")
+
 def open_miniimage(space):
     return squeakimage.ImageReader(space, squeakimage.Stream(mini_image.open()))
 
@@ -192,7 +206,7 @@
     # Should get this from w_object
     w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS)
     s_class = w_object.shadow_of_my_class(space)
-    w_method = s_class.lookup("abs")
+    w_method = s_class.lookup(find_symbol("abs"))
 
     assert w_method
     w_frame = w_method.create_frame(space, w_object, [])
@@ -286,7 +300,11 @@
 def perform(w_receiver, selector, *arguments_w):
     interp = interpreter.Interpreter(space)
     s_class = w_receiver.shadow_of_my_class(space)
-    w_method = s_class.lookup(selector)
+    if isinstance(selector, str):
+        w_selector = find_symbol(selector)
+    else:
+        w_selector = selector
+    w_method = s_class.lookup(w_selector)
     assert w_method
     w_frame = w_method.create_frame(space, w_receiver, list(arguments_w))
     interp.store_w_active_context(w_frame)
diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py
--- a/spyvm/test/test_model.py
+++ b/spyvm/test/test_model.py
@@ -6,6 +6,8 @@
 mockclass = objspace.bootstrap_class
 
 space = objspace.ObjSpace()
+w_foo = space.wrap_string("foo")
+w_bar = space.wrap_string("bar")
 
 def joinbits(values, lengths):
     result = 0
@@ -59,29 +61,29 @@
 def test_method_lookup():
     w_class = mockclass(space, 0)
     shadow = w_class.as_class_get_shadow(space)
-    shadow.installmethod("foo", 1)
-    shadow.installmethod("bar", 2)
+    shadow.installmethod(w_foo, 1)
+    shadow.installmethod(w_bar, 2)
     w_subclass = mockclass(space, 0, w_superclass=w_class)
     subshadow = w_subclass.as_class_get_shadow(space)
     assert subshadow.s_superclass() is shadow
-    subshadow.installmethod("foo", 3)
+    subshadow.installmethod(w_foo, 3)
     shadow.initialize_methoddict()
     subshadow.initialize_methoddict()
-    assert shadow.lookup("foo") == 1
-    assert shadow.lookup("bar") == 2
+    assert shadow.lookup(w_foo) == 1
+    assert shadow.lookup(w_bar) == 2
     py.test.raises(MethodNotFound, shadow.lookup, "zork")
-    assert subshadow.lookup("foo") == 3
-    assert subshadow.lookup("bar") == 2
+    assert subshadow.lookup(w_foo) == 3
+    assert subshadow.lookup(w_bar) == 2
     py.test.raises(MethodNotFound, subshadow.lookup, "zork")
 
 def test_w_compiledin():
     w_super = mockclass(space, 0)
     w_class = mockclass(space, 0, w_superclass=w_super)
     supershadow = w_super.as_class_get_shadow(space)
-    supershadow.installmethod("foo", model.W_CompiledMethod(0))
+    supershadow.installmethod(w_foo, model.W_CompiledMethod(0))
     classshadow = w_class.as_class_get_shadow(space)
     classshadow.initialize_methoddict()
-    assert classshadow.lookup("foo").as_compiledmethod_get_shadow(space).w_compiledin is w_super
+    assert classshadow.lookup(w_foo).as_compiledmethod_get_shadow(space).w_compiledin is w_super
 
 def test_compiledmethod_setchar():
     w_method = model.W_CompiledMethod(3)
diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py
--- a/spyvm/test/test_shadow.py
+++ b/spyvm/test/test_shadow.py
@@ -69,7 +69,10 @@
                'bar': model.W_CompiledMethod(0)}
     w_class = build_smalltalk_class("Demo", 0x90, methods=methods)
     classshadow = w_class.as_class_get_shadow(space)
-    assert classshadow.s_methoddict().methoddict == methods
+    methoddict = classshadow.s_methoddict().methoddict
+    assert len(methods) == len(methoddict)
+    for w_key, value in methoddict.items():
+        assert methods[w_key.as_string()] is value
 
 def method(tempsize=3,argsize=2, bytes="abcde"):
     w_m = model.W_CompiledMethod()


More information about the pypy-commit mailing list