[pypy-commit] lang-smalltalk default: merge default

timfel noreply at buildbot.pypy.org
Fri Apr 12 10:29:59 CEST 2013


Author: Tim Felgentreff <timfelgentreff at gmail.com>
Branch: 
Changeset: r261:6194910649dc
Date: 2013-04-12 10:28 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/6194910649dc/

Log:	merge default

diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs
--- a/BitBltSim.19.cs
+++ b/BitBltSim.19.cs
@@ -94,7 +94,8 @@
 	simDestRaster _ destForm width - 1 // WordSize + 1.
 	sourceForm notNil
 		ifTrue: [simSourceBits _ sourceForm bits.
-				simSourceRaster _ sourceForm width - 1 // WordSize + 1].
+				simSourceRaster _ sourceForm width - 1 // WordSize + 1]
+		ifFalse: [simSourceRaster _ 0].
 	halftoneForm notNil
 		ifTrue: [simHalftoneBits _ halftoneForm bits].
 	simSkew _ (simSx - simDx) bitAnd: WordSize0.
@@ -118,45 +119,37 @@
 
 !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'!
 copyLoop
-	| prevWord thisWord skewWord mergeMask
-	  halftoneWord mergeWord |
-	1 to: simH do: "here is the vertical loop"
+	| prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask |
+	noSimSkewMask _ simSkewMask bitInvert32.
+	1 to: simH do: 
 		[:i | 
-		(halftoneForm notNil)
-			ifTrue:
-				"XXX Accessing simHalftoneBits with wrap-around ... different from BlueBook"
-				[halftoneWord _ simHalftoneBits at: (1 + (simDy \\ simHalftoneBits size)).
+		halftoneForm notNil
+			ifTrue: 
+				[halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size).
 				simDy _ simDy + simVDir]
 			ifFalse: [halftoneWord _ AllOnes].
 		skewWord _ halftoneWord.
 		simPreload
-			ifTrue: [prevWord _ simSourceBits at: simSourceIndex + 1.
-					"load the 32bit shifter. TODO: check if this is WordSize dependent"
-					simSourceIndex _ simSourceIndex + simHDir]
+			ifTrue: 
+				[prevWord _ simSourceBits at: simSourceIndex + 1.
+				simSourceIndex _ simSourceIndex + simHDir]
 			ifFalse: [prevWord _ 0].
 		mergeMask _ simMask1.
-		1 to: simNWords do: "here is the inner horizontal loop"
-			[:word |
-			sourceForm notNil "if source is used"
-				ifTrue:
-					[prevWord _ prevWord bitAnd: simSkewMask.
-						    "XXX: Hack to work around out-of-bounds access"
-					thisWord := simSourceBits at: (simSourceIndex \\ simSourceBits size) + 1.
-										      	 "pick up next word"
-					skewWord _
-						prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32).
-					prevWord _ thisWord.
-					"Change from BB: bitAnd: AllOnes to stay in word bounds"
-					skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr:
-											(skewWord bitShift: simSkew - WordSize)].
-															"WordSize-bit rotate"
-			mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
-								with: (simDestBits at: simDestIndex + 1).
-			simDestBits
-				at: simDestIndex + 1
-				put: ((mergeMask bitAnd: mergeWord)
-								bitOr: (mergeMask bitInvert32
-									bitAnd: (simDestBits at: simDestIndex + 1))).
+		1 to: simNWords do: 
+			[:word | 
+			sourceForm notNil
+				ifTrue: 
+					[thisWord _ (simSourceIndex <= 0 or: [simSourceIndex >= simSourceBits size])
+								ifTrue: [simSourceBits at: 1]
+								ifFalse: [simSourceBits at: simSourceIndex + 1].
+					prevWord _ (prevWord bitAnd: simSkewMask) bitShift: simSkew.
+					skewWord _ prevWord bitOr: ((thisWord bitAnd: noSimSkewMask) bitShift: simSkew - WordSize).
+					prevWord _ thisWord].
+			halftoneForm notNil 
+				ifTrue: [mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
+						with: (simDestBits at: simDestIndex + 1)].
+			simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord)
+					bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))).
 			simSourceIndex _ simSourceIndex + simHDir.
 			simDestIndex _ simDestIndex + simHDir.
 			word = (simNWords - 1)
@@ -190,7 +183,6 @@
 
 	destForm unhibernate.
 	sourceForm
-		ifNil: [sourceForm := destForm]
 		ifNotNil: [sourceForm unhibernate].
 	halftoneForm ifNotNil: [
 		(halftoneForm isKindOf: Form)
@@ -220,6 +212,7 @@
 				simDy _ clipY].
 	simDy + simH > (clipY + clipHeight)
 		ifTrue: [simH _ simH - ((simDy + simH) - (clipY + clipHeight))].
+	sourceForm isNil ifTrue: [^nil].
 	simSx < 0
 		ifTrue: [simDx _ simDx - simSx. simW _ simW + simSx. simSx _ 0].
 	simSx + simW > sourceForm width
diff --git a/images/minibluebookdebug.image b/images/minibluebookdebug.image
index 55870b1f6092dbfa3dcb4e4d0c46fec62b223bf2..72834c73d01e0d5de097c1c824971bd952d0e6e8
GIT binary patch

[cut]

diff --git a/spyvm/display.py b/spyvm/display.py
--- a/spyvm/display.py
+++ b/spyvm/display.py
@@ -1,6 +1,7 @@
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.runicode import unicode_encode_utf_8
+from rpython.rlib import jit
 
 from rsdl import RSDL, RSDL_helper
 
@@ -58,26 +59,11 @@
         self.depth = d
         self.screen = RSDL.SetVideoMode(w, h, 32, 0)
         assert self.screen
-        # self.fillwhite()
 
-    def set_pixelbuffer(self, pixelbuffer):
-        if self.has_surface:
-            RSDL.FreeSurface(self.surface)
-        pitch = 4 * self.width
-        rmask, gmask, bmask, amask = r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0xFF000000)
-        self.surface = RSDL.CreateRGBSurfaceFrom(rffi.cast(rffi.VOIDP, pixelbuffer),
-                                                 self.width, self.height, 32, pitch,
-                                                 rmask, gmask, bmask, amask)
-        self.has_surface = True
+    def get_pixelbuffer(self):
+        return self.screen.c_pixels
 
-    def fillwhite(self):
-        fmt = self.screen.c_format
-        color = RSDL.MapRGB(fmt, 255, 255, 255)
-        RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color)
-        RSDL.Flip(self.screen)
-
-    def blit(self):
-        RSDL.BlitSurface(self.surface, lltype.nullptr(RSDL.Rect), self.screen, lltype.nullptr(RSDL.Rect))
+    def flip(self):
         RSDL.Flip(self.screen)
 
     def get_next_event(self):
diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py
new file mode 100644
--- /dev/null
+++ b/spyvm/fieldtypes.py
@@ -0,0 +1,167 @@
+from spyvm import model, shadow
+
+from rpython.rlib import objectmodel, jit, signature
+
+class TypeTag():
+    pass
+
+LPI = TypeTag()
+SInt = TypeTag()
+flt = TypeTag()
+obj = TypeTag()
+
+maps = {}
+
+class VarSizedFieldTypes():
+    _immutable_fields_ = []
+    _attrs_ = []
+    _settled_ = True
+
+    @staticmethod
+    def of_length(s_class, n):
+        return nilTyper
+
+    def __init__(self):
+        pass
+
+    def fetch(self, w_obj, n0):
+        return w_obj._vars[n0]
+
+    def store(self, w_obj, n0, w_val):
+        w_obj._vars[n0] = w_val
+
+class FieldTypes(VarSizedFieldTypes):
+    _immutable_fields_ = ['types']
+    _attrs_ = ['types', 'parent', 'siblings', 'diff']
+    _settled_ = True
+
+    def __init__(self, types, parent=None, change=(-1, obj)):
+        self.types = types
+        self.parent = parent
+        if parent is not None:
+            assert change != (-1, obj)
+        self.diff = change
+
+        self.siblings = {}
+
+    def fetch(self, w_object, n0):
+        w_result = w_object._vars[n0]
+        assert w_result is not None
+        types = self.types
+        if types[n0] is SInt:
+            jit.record_known_class(w_result, model.W_SmallInteger)
+        elif types[n0] is LPI:
+            jit.record_known_class(w_result, model.W_LargePositiveInteger1Word)
+        elif types[n0] is flt:
+            jit.record_known_class(w_result, model.W_Float)
+        return w_result
+
+    def store(self, w_object, n0, w_value):
+        types = self.types
+        changed_type = w_value.fieldtype()
+        if types[n0] is not changed_type:
+            w_object.fieldtypes = self.sibling(n0, changed_type)
+        w_object._vars[n0] = w_value
+
+
+    def sibling(self, n0, changed_type):
+        assert self.types[n0] is not changed_type
+        change = (n0, changed_type)
+        parent = self.parent
+        siblings = self.siblings
+        if change in siblings:
+            return siblings[change]
+        elif parent is None:
+            return self.descent([change])
+        else:
+            new_fieldtype = parent.ascent([change, self.diff])
+            if not objectmodel.we_are_translated():
+                assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:]
+            siblings[change] = new_fieldtype
+            return new_fieldtype
+
+    def ascent(self, changes):
+        parent = self.parent
+        if parent is None:
+            sort(changes)
+            return self.descent(changes)
+        else:
+            change = self.diff
+            if changes[0][0] != change[0]:
+                changes.append(change)
+            return parent.ascent(changes)
+
+    def descent(self, changes):
+        if changes == []:
+            return self
+
+        change = changes[0]
+        siblings = self.siblings
+        if change in siblings:
+            return siblings[change].descent(changes[1:])
+        else:
+            new_types = list(self.types)
+            new_types[change[0]] = change[1]
+            new_fieldtype = FieldTypes(new_types, self, change)
+            siblings[change] = new_fieldtype
+            return new_fieldtype.descent(changes[1:])
+
+
+    @staticmethod
+    def of_length(n):
+        if n not in maps:
+            maps[n] = FieldTypes([obj] * n)
+        return maps[n]
+
+
+nilTyper = VarSizedFieldTypes()
+def fieldtypes_of_length(s_class, size):
+    if s_class is None or s_class.isvariable():
+        return nilTyper
+    else:
+        return FieldTypes.of_length(size)
+
+def fieldtypes_of(w_obj):
+    try:
+        if w_obj.s_class.isvariable():
+            return nilTyper
+        else:
+            vars = w_obj._vars
+            size = len(vars)
+            typer = FieldTypes.of_length(size)
+            for i, w_val in enumerate(vars):
+                changed_type = w_val.fieldtype()
+                if changed_type is not obj:
+                    typer = typer.sibling(i, changed_type)
+            return typer
+    except AttributeError:
+        return nilTyper
+
+def sort(an_array):
+    end = len(an_array) - 1
+    sort_quick_inplace(an_array, 0, end)
+
+
+def sort_quick_inplace(an_array, start, end):
+    assert start >= 0 and end < len(an_array)
+
+    def partition(an_array, start, end):
+        key = an_array[start][0]
+        i = start - 1
+        j = end + 1
+        while True:
+            i += 1
+            j -= 1
+            while not an_array[j][0] <= key:
+                j -= 1
+            while not an_array[i][0] >= key:
+                i += 1
+            if j <= i:
+                return j
+            else:
+                an_array[i], an_array[j] = an_array[j], an_array[i]
+
+    if start < end:
+        mid = partition(an_array, start, end)
+        sort_quick_inplace(an_array, start, mid)
+        sort_quick_inplace(an_array, mid + 1, end)
\ No newline at end of file
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -17,7 +17,7 @@
 import sys
 from spyvm import constants, error
 
-from rpython.rlib import rrandom, objectmodel, jit
+from rpython.rlib import rrandom, objectmodel, jit, signature
 from rpython.rlib.rarithmetic import intmask, r_uint
 from rpython.tool.pairtype import extendabletype
 from rpython.rlib.objectmodel import instantiate, compute_hash
@@ -127,6 +127,13 @@
     def rshift(self, space, shift):
         raise error.PrimitiveFailedError()
 
+    def unwrap_uint(self, space):
+        raise error.UnwrappingError("Got unexpected class in unwrap_uint")
+
+    def fieldtype(self):
+        from spyvm.fieldtypes import obj
+        return obj
+
 class W_SmallInteger(W_Object):
     """Boxed integer value"""
     # TODO can we tell pypy that its never larger then 31-bit?
@@ -165,6 +172,14 @@
     def rshift(self, space, shift):
         return space.wrap_int(self.value >> shift)
 
+    def unwrap_uint(self, space):
+        from rpython.rlib.rarithmetic import r_uint
+        val = self.value
+        if val < 0:
+            raise error.UnwrappingError("got negative integer")
+        return r_uint(val)
+
+
     @jit.elidable
     def as_repr_string(self):
         return "W_SmallInteger(%d)" % self.value
@@ -189,6 +204,10 @@
     def clone(self, space):
         return self
 
+    def fieldtype(self):
+        from spyvm.fieldtypes import SInt
+        return SInt
+
 class W_AbstractObjectWithIdentityHash(W_Object):
     """Object with explicit hash (ie all except small
     ints and floats)."""
@@ -262,6 +281,10 @@
         # and only in this case we do need such a mask
         return space.wrap_int((self.value >> shift) & mask)
 
+    def unwrap_uint(self, space):
+        from rpython.rlib.rarithmetic import r_uint
+        return r_uint(self.value)
+
     def clone(self, space):
         return W_LargePositiveInteger1Word(self.value)
 
@@ -288,6 +311,10 @@
     def invariant(self):
         return isinstance(self.value, int)
 
+    def fieldtype(self):
+        from spyvm.fieldtypes import LPI
+        return LPI
+
 class W_Float(W_AbstractObjectWithIdentityHash):
     """Boxed float value."""
     _attrs_ = ['value']
@@ -373,7 +400,11 @@
     def size(self):
         return 2
 
+    def fieldtype(self):
+        from spyvm.fieldtypes import flt
+        return flt
 
+ at signature.finishsigs
 class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash):
     """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or
     Float)."""
@@ -422,30 +453,40 @@
     def has_class(self):
         return self.s_class is not None
 
+    # we would like the following, but that leads to a recursive import
+    #@signature(signature.types.self(), signature.type.any(),
+    #           returns=signature.types.instance(ClassShadow))
     def shadow_of_my_class(self, space):
-        assert self.s_class is not None
-        return self.s_class
+        s_class = self.s_class
+        assert s_class is not None
+        return s_class
 
 class W_PointersObject(W_AbstractObjectWithClassReference):
     """Common object."""
-    _attrs_ = ['_shadow', '_vars']
+    _attrs_ = ['_shadow', '_vars', 'fieldtypes']
 
     _shadow = None # Default value
 
     @jit.unroll_safe
     def __init__(self, space, w_class, size):
+        from spyvm.fieldtypes import fieldtypes_of_length
         """Create new object with size = fixed + variable size."""
         W_AbstractObjectWithClassReference.__init__(self, space, w_class)
+
         vars = self._vars = [None] * size
+        self.fieldtypes = fieldtypes_of_length(self.s_class, size)
+
         for i in range(size): # do it by hand for the JIT's sake
             vars[i] = w_nil
         self._shadow = None # Default value
 
     def fillin(self, space, g_self):
+        from spyvm.fieldtypes import fieldtypes_of
         self._vars = g_self.get_pointers()
         self.s_class = g_self.get_class().as_class_get_penumbra(space)
         self.hash = g_self.get_hash()
         self.space = space
+        self.fieldtypes = fieldtypes_of(self)
 
     def at0(self, space, index0):
         # To test, at0 = in varsize part
@@ -461,7 +502,9 @@
         return self._fetch(n0)
 
     def _fetch(self, n0):
-        return self._vars[n0]
+        # return self._vars[n0]
+        fieldtypes = jit.promote(self.fieldtypes)
+        return fieldtypes.fetch(self, n0)
 
     def store(self, space, n0, w_value):
         if self.has_shadow():
@@ -469,8 +512,9 @@
         return self._store(n0, w_value)
 
     def _store(self, n0, w_value):
-        self._vars[n0] = w_value
-
+        # self._vars[n0] = w_value
+        fieldtypes = jit.promote(self.fieldtypes)
+        return fieldtypes.store(self, n0, w_value)
 
     def varsize(self, space):
         return self.size() - self.instsize(space)
@@ -525,10 +569,13 @@
     # Should only be used during squeak-image loading.
     def as_class_get_penumbra(self, space):
         from spyvm.shadow import ClassShadow
-        assert self._shadow is None or isinstance(self._shadow, ClassShadow)
-        if self._shadow is None:
-            self.store_shadow(ClassShadow(space, self))
-        return self._shadow
+        s_class = self._shadow
+        if s_class is None:
+            s_class = ClassShadow(space, self)
+            self.store_shadow(s_class)
+        else:
+            assert isinstance(s_class, ClassShadow)
+        return s_class
 
     def as_blockcontext_get_shadow(self, space):
         from spyvm.shadow import BlockContextShadow
@@ -575,7 +622,8 @@
         return True
 
     def clone(self, space):
-        w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars))
+        w_result = W_PointersObject(self.space, self.getclass(space),
+                                    len(self._vars))
         w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))]
         return w_result
 
@@ -585,6 +633,10 @@
                                 className='W_PointersObject', 
                                 additionalInformation='len=%d' % self.size())
 
+    def fieldtype(self):
+        from spyvm.fieldtypes import obj
+        return obj
+
 class W_BytesObject(W_AbstractObjectWithClassReference):
     _attrs_ = ['bytes']
 
@@ -644,6 +696,16 @@
         w_result.bytes = list(self.bytes)
         return w_result
 
+    def unwrap_uint(self, space):
+        # TODO: Completely untested! This failed translation bigtime...
+        # XXX Probably we want to allow all subclasses
+        if not self.getclass(space).is_same_object(space.w_LargePositiveInteger):
+            raise error.UnwrappingError("Failed to convert bytes to word")
+        word = 0 
+        for i in range(self.size()):
+            word += r_uint(ord(self.getchar(i))) << 8*i
+        return word
+
 class W_WordsObject(W_AbstractObjectWithClassReference):
     _attrs_ = ['words']
 
@@ -698,14 +760,11 @@
 
     def __init__(self, space, w_class, size, depth, display):
         W_AbstractObjectWithClassReference.__init__(self, space, w_class)
-        bytelen = NATIVE_DEPTH / depth * size
-        self.pixelbuffer = lltype.malloc(rffi.ULONGP.TO, bytelen, flavor='raw')
+        self._real_depth_buffer = [0] * size
+        self.pixelbuffer = display.get_pixelbuffer()
         self._realsize = size
         self.display = display
 
-    def __del__(self):
-        lltype.free(self.pixelbuffer, flavor='raw')
-
     def at0(self, space, index0):
         val = self.getword(index0)
         return space.wrap_uint(val)
@@ -715,7 +774,7 @@
         self.setword(index0, word)
 
     def flush_to_screen(self):
-        self.display.blit()
+        self.display.flip()
 
     def size(self):
         return self._realsize
@@ -739,28 +798,23 @@
 
 
 class W_DisplayBitmap1Bit(W_DisplayBitmap):
-    @jit.unroll_safe
     def getword(self, n):
-        word = r_uint(0)
-        pos = n * NATIVE_DEPTH
-        for i in xrange(32):
-            word <<= 1
-            pixel = self.pixelbuffer[pos]
-            word |= r_uint(pixel & 0x1)
-            pos += 1
-        return ~word
+        return self._real_depth_buffer[n]
 
     @jit.unroll_safe
     def setword(self, n, word):
-        pos = n * NATIVE_DEPTH
+        self._real_depth_buffer[n] = word
+        pos = n * NATIVE_DEPTH * 4
         mask = r_uint(1)
         mask <<= 31
         for i in xrange(32):
             bit = mask & word
-            pixel = r_uint((0x00ffffff * (bit == 0)) | r_uint(0xff000000))
-            self.pixelbuffer[pos] = pixel
+            self.pixelbuffer[pos] = rffi.r_uchar(0xff * (bit == 0))
+            self.pixelbuffer[pos + 1] = rffi.r_uchar(0xff * (bit == 0))
+            self.pixelbuffer[pos + 2] = rffi.r_uchar(0xff * (bit == 0))
+            self.pixelbuffer[pos + 3] = rffi.r_uchar(0xff)
             mask >>= 1
-            pos += 1
+            pos += 4
 
 
 # XXX Shouldn't compiledmethod have class reference for subclassed compiled
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -1,5 +1,6 @@
 from spyvm import constants, model, shadow, wrapper
 from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError
+from rpython.rlib import jit
 from rpython.rlib.objectmodel import instantiate, specialize
 from rpython.rlib.rarithmetic import intmask, r_uint, int_between
 
@@ -192,11 +193,14 @@
         if bytes_len <= 4:
             return self.wrap_positive_32bit_int(intmask(val))
         else:
-            w_result = model.W_BytesObject(self, 
-                        self.classtable['w_LargePositiveInteger'], bytes_len)
-            for i in range(bytes_len):
-                w_result.setchar(i, chr(intmask((val >> i*8) & 255)))
-            return w_result
+            return self._wrap_uint_loop(val, bytes_len)
+
+    def _wrap_uint_loop(self, val, bytes_len):
+        w_result = model.W_BytesObject(self,
+                    self.classtable['w_LargePositiveInteger'], bytes_len)
+        for i in range(bytes_len):
+            w_result.setchar(i, chr(intmask((val >> i*8) & 255)))
+        return w_result
 
     def wrap_positive_32bit_int(self, val):
         # This will always return a positive value.
@@ -247,24 +251,7 @@
         raise UnwrappingError("expected a W_SmallInteger or W_LargePositiveInteger1Word, got %s" % (w_value,))
 
     def unwrap_uint(self, w_value):
-        if isinstance(w_value, model.W_SmallInteger):
-            val = w_value.value
-            if val < 0:
-                raise UnwrappingError("got negative integer")
-            return r_uint(w_value.value)
-        elif isinstance(w_value, model.W_LargePositiveInteger1Word):
-            return r_uint(w_value.value)
-        elif isinstance(w_value, model.W_BytesObject):
-            # TODO: Completely untested! This failed translation bigtime...
-            # XXX Probably we want to allow all subclasses
-            if not w_value.getclass(self).is_same_object(self.w_LargePositiveInteger):
-                raise UnwrappingError("Failed to convert bytes to word")
-            word = 0 
-            for i in range(w_value.size()):
-                word += r_uint(ord(w_value.getchar(i))) << 8*i
-            return word
-        else:
-            raise UnwrappingError("Got unexpected class in unwrap_uint")
+        return w_value.unwrap_uint(self)
 
     def unwrap_positive_32bit_int(self, w_value):
         if isinstance(w_value, model.W_SmallInteger):
@@ -297,6 +284,8 @@
         if not isinstance(w_v, model.W_PointersObject):
             raise UnwrappingError()
         return w_v
+
+    @jit.look_inside_iff(lambda self, w_array: jit.isconstant(w_array.size()))
     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):
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -321,6 +321,14 @@
 
 FAIL = 19
 
+ at expose_primitive(FAIL)
+def func(interp, s_frame, argcount):
+    from spyvm.interpreter import ReturnFromTopLevel
+    if s_frame.w_method()._likely_methodname == 'doesNotUnderstand:':
+        print 'Probably Debugger called...'
+        raise ReturnFromTopLevel(interp.space.wrap_string("debugger called"))
+    raise PrimitiveFailedError()
+
 # ___________________________________________________________________________
 # Subscript and Stream Primitives
 
@@ -592,15 +600,18 @@
         w_prev_bitmap = w_prev_display.fetch(interp.space, 0)
         if isinstance(w_prev_bitmap, model.W_DisplayBitmap):
             sdldisplay = w_prev_bitmap.display
+            sdldisplay.set_video_mode(width, height, depth)
 
     if isinstance(w_bitmap, model.W_DisplayBitmap):
         assert (sdldisplay is None) or (sdldisplay is w_bitmap.display)
         sdldisplay = w_bitmap.display
+        sdldisplay.set_video_mode(width, height, depth)
         w_display_bitmap = w_bitmap
     else:
         assert isinstance(w_bitmap, model.W_WordsObject)
         if not sdldisplay:
             sdldisplay = display.SDLDisplay(interp.image_name)
+            sdldisplay.set_video_mode(width, height, depth)
         w_display_bitmap = model.W_DisplayBitmap.create(
             interp.space,
             w_bitmap.getclass(interp.space),
@@ -612,9 +623,7 @@
             w_display_bitmap.setword(idx, word)
         w_rcvr.store(interp.space, 0, w_display_bitmap)
 
-    sdldisplay.set_video_mode(width, height, depth)
-    sdldisplay.set_pixelbuffer(w_display_bitmap.pixelbuffer)
-    sdldisplay.blit()
+    w_display_bitmap.flush_to_screen()
 
     interp.space.objtable['w_display'] = w_rcvr
     return w_rcvr
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -201,7 +201,8 @@
     def new(self, extrasize=0):
         w_cls = self.w_self()
         if self.instance_kind == POINTERS:
-            w_new = model.W_PointersObject(self.space, w_cls, self.instsize()+extrasize)
+            size = self.instsize() + extrasize
+            w_new = model.W_PointersObject(self.space, w_cls, size)
         elif self.instance_kind == WORDS:
             w_new = model.W_WordsObject(self.space, w_cls, extrasize)
         elif self.instance_kind == BYTES:
diff --git a/spyvm/test/test_fieldtypes.py b/spyvm/test/test_fieldtypes.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/test_fieldtypes.py
@@ -0,0 +1,33 @@
+import py
+from spyvm import model, fieldtypes
+from spyvm import objspace
+
+from spyvm.fieldtypes import obj, SInt
+
+def test_simple_changes():
+	a = fieldtypes.FieldTypes.of_length(3)
+	assert a.types == [obj, obj, obj]
+	b = a.sibling(1, SInt)
+	assert b.types == [obj, SInt, obj]
+	c = a.sibling(1, SInt)
+	assert b is c
+
+def test_two_level_changes_identity():
+	a = fieldtypes.FieldTypes.of_length(3)
+	b = a.sibling(1, SInt)
+	c = a.sibling(0, SInt)
+	d = b.sibling(0, SInt)
+	assert d.types == [SInt, SInt, obj]
+	e = c.sibling(1, SInt)
+	assert d is e
+
+def test_numberOfElements():
+	a = fieldtypes.FieldTypes.of_length(3)
+	a.sibling(0, SInt).sibling(1, SInt).sibling(2, SInt)
+	a.sibling(1, SInt).sibling(2, SInt)
+	a.sibling(2, SInt).sibling(0, SInt)
+	assert a.sibling(2, SInt).sibling(0, SInt).parent is a.sibling(0, SInt)
+	assert len(a.siblings) == 3
+	assert len(a.sibling(0, SInt).siblings) == 2
+	assert len(a.sibling(1, SInt).siblings) == 2
+	assert len(a.sibling(2, SInt).siblings) == 1 # link to [o, i, i] not created
\ No newline at end of file
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
@@ -2,7 +2,10 @@
 from spyvm import model, interpreter, primitives, shadow
 from spyvm import objspace, wrapper, constants
 
-mockclass = objspace.bootstrap_class
+def mockclass(space, instsize, w_superclass=None, w_metaclass=None,
+                    name='?', format=shadow.POINTERS, varsized=True):
+    return objspace.bootstrap_class(space, instsize, w_superclass, w_metaclass,
+                    name, format, varsized)
 
 space = objspace.ObjSpace()
 interp = interpreter.Interpreter(space)
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
@@ -92,9 +92,9 @@
     w_object.store(space, constants.MTHDCTX_METHOD, method)
     # XXX
     w_object.store(space, constants.MTHDCTX_CLOSURE_OR_NIL, space.w_nil)
-    w_object.store(space, constants.MTHDCTX_RECEIVER, 'receiver')
+    w_object.store(space, constants.MTHDCTX_RECEIVER, space.wrap_string('receiver'))
 
-    w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, 'el')
+    w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, space.wrap_string('el'))
     return w_object
 
 def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5,
@@ -106,7 +106,7 @@
     w_object.store(space, constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, space.wrap_int(54))
     w_object.store(space, constants.BLKCTX_INITIAL_IP_INDEX, space.wrap_int(17))
     w_object.store(space, constants.BLKCTX_HOME_INDEX, home)
-    w_object.store(space, constants.BLKCTX_STACK_START, 'el')
+    w_object.store(space, constants.BLKCTX_STACK_START, space.wrap_string('el'))
     return w_object
 
 def test_context():
@@ -121,24 +121,24 @@
     assert s_object2.w_self() == w_object2
     assert s_object.s_sender() == None
     assert s_object2.s_sender() == s_object
-    assert s_object.w_receiver() == 'receiver'
+    assert s_object.w_receiver().as_string() == 'receiver'
     s_object2.settemp(0, 'a')
     s_object2.settemp(1, 'b')
     assert s_object2.gettemp(1) == 'b'
     assert s_object2.gettemp(0) == 'a'
     assert s_object.w_method() == w_m
     idx = s_object.stackstart()
-    w_object.store(space, idx, 'f')
-    w_object.store(space, idx + 1, 'g')
-    w_object.store(space, idx + 2, 'h')
-    assert s_object.stack() == ['f', 'g', 'h' ]
-    assert s_object.top() == 'h'
+    w_object.store(space, idx, space.wrap_string('f'))
+    w_object.store(space, idx + 1, space.wrap_string('g'))
+    w_object.store(space, idx + 2, space.wrap_string('h'))
+    assert map(lambda x: x.as_string(), s_object.stack()) == ['f', 'g', 'h' ]
+    assert s_object.top().as_string() == 'h'
     s_object.push('i')
     assert s_object.top() == 'i'
-    assert s_object.peek(1) == 'h'
+    assert s_object.peek(1).as_string() == 'h'
     assert s_object.pop() == 'i'
-    assert s_object.pop_and_return_n(2) == ['g', 'h']
-    assert s_object.pop() == 'f'
+    assert map(lambda x: x.as_string(), s_object.pop_and_return_n(2)) == ['g', 'h']
+    assert s_object.pop().as_string() == 'f'
     assert s_object.external_stackpointer() == s_object.stackstart()
 
 def test_methodcontext():


More information about the pypy-commit mailing list