[pypy-svn] r47839 - in pypy/dist/pypy/lang/smalltalk: . test
akuhn at codespeak.net
akuhn at codespeak.net
Wed Oct 24 17:49:18 CEST 2007
Author: akuhn
Date: Wed Oct 24 17:49:17 2007
New Revision: 47839
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_model.py
pypy/dist/pypy/lang/smalltalk/test/test_primitives.py
pypy/dist/pypy/lang/smalltalk/test/test_squeakimage.py
Log:
(akuhn, tverwaes)
got sidetracked while implementing some image loading code. we removed knowledge about number of named inst vars from W_Class / W_Object as this is not trivially known to the VM
Modified: pypy/dist/pypy/lang/smalltalk/model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/model.py (original)
+++ pypy/dist/pypy/lang/smalltalk/model.py Wed Oct 24 17:49:17 2007
@@ -1,5 +1,5 @@
-class W_Object:
+class W_Object(object):
def __init__(self, w_class):
self.w_class = w_class
self.w_hash = None # XXX initial value?
@@ -8,17 +8,35 @@
return 0
def instvarsize(self):
- return self.w_class.instvarsize
+ return self.w_class.instvarsize
+
+ def invariant(self):
+ return (hasattr(self, 'w_class') and
+ self.w_class != None)
+
+ def as_w_class_instvarsize(self):
+ return self.vars[3] # hardcoded position of instvar
class W_SmallInteger(W_Object):
def __init__(self, w_class, value):
W_Object.__init__(self, w_class)
self.value = value
+
+ def invariant(self):
+ W_Object.invariant(self)
+ assert hasattr(self, 'value')
+ assert self.value != None
class W_Float(W_Object):
def __init__(self, w_class, value):
W_Object.__init__(self, w_class)
self.value = value
+
+ def invariant(self):
+ return (W_Object.invariant(self) and
+ hasattr(self, 'value') and
+ self.value != None)
+
class W_PointersObject(W_Object):
""" The normal object """
@@ -26,22 +44,33 @@
W_Object.__init__(self, w_class)
self.vars = [None] * (w_class.instvarsize + size)
- def getnamedvar(self, index):
- if not index < self.w_class.instvarsize: raise IndexError
+ def fetch(self, index):
return self.vars[index]
+
+ def store(self, index, w_value):
+ self.vars[index] = w_value
+
+ def getnamedvar(self, index):
+ print "deprecated"
+ return self.fetch(index)
def setnamedvar(self, index, w_value):
- if not index < self.w_class.instvarsize: raise IndexError
- self.vars[index] = w_value
+ print "deprecated"
+ return self.store(index, w_value)
def size(self):
- return len(self.vars) - self.w_class.instvarsize
+ return len(self.vars)
def getindexedvar(self, index):
- return self.vars[index + self.w_class.instvarsize]
+ raise NotImplementedError
def setindexedvar(self, index, w_value):
- self.vars[index + self.w_class.instvarsize] = w_value
+ raise NotImplementedError
+
+ def invariant(self):
+ return (W_Object.invariant(self) and
+ hasattr(self, 'vars') and
+ self.vars != None)
class W_BytesObject(W_Object):
@@ -58,6 +87,12 @@
def size(self):
return len(self.bytes)
+ def invariant(self):
+ return (W_Object.invariant(self) and
+ hasattr(self, 'bytes') and
+ self.bytes != None)
+
+
class W_WordsObject(W_Object):
def __init__(self, w_class, size):
W_Object.__init__(self, w_class)
@@ -70,7 +105,12 @@
self.words[n] = word
def size(self):
- return len(self.words)
+ return len(self.words)
+
+ def invariant(self):
+ return (W_Object.invariant(self) and
+ hasattr(self, 'words') and
+ self.words != None)
class W_CompiledMethod(W_Object):
"""My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances intermix both indexable pointer fields and indexable integer fields.
@@ -109,6 +149,19 @@
assert len(arguments) == self.argsize
return W_ContextFrame(None, self, receiver, arguments, sender)
+ def invariant(self):
+ return (W_Object.invariant(self) and
+ hasattr(self, 'literals') and
+ self.literals != None and
+ hasattr(self, 'bytes') and
+ self.bytes != None and
+ hasattr(self, 'argsize') and
+ self.argsize != None and
+ hasattr(self, 'tempsize') and
+ self.tempsize != None and
+ hasattr(self, 'primitive') and
+ self.primitive != None)
+
# ____________________________________________________________
POINTERS = 0
Modified: pypy/dist/pypy/lang/smalltalk/primitives.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/primitives.py (original)
+++ pypy/dist/pypy/lang/smalltalk/primitives.py Wed Oct 24 17:49:17 2007
@@ -142,13 +142,13 @@
@stack(2)
def func(stack):
idx, w_obj = common_at(stack)
- return w_obj.getindexedvar(idx)
+ return w_obj.fetch(idx)
@primitive(AT_PUT)
@stack(3)
def func(stack):
w_val, idx, w_obj = common_at_put(stack)
- w_obj.setindexedvar(idx, w_val)
+ w_obj.store(idx, w_val)
return w_val
@primitive(SIZE)
Modified: pypy/dist/pypy/lang/smalltalk/squeakimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/squeakimage.py (original)
+++ pypy/dist/pypy/lang/smalltalk/squeakimage.py Wed Oct 24 17:49:17 2007
@@ -1,14 +1,23 @@
import py
-import struct
from pypy.lang.smalltalk import model
from pypy.lang.smalltalk import fakeimage
from pypy.rlib import objectmodel
def int2str(integer):
- return (chr((integer & 0xff000000) >> 24) +
- chr((integer & 0x00ff0000) >> 16) +
- chr((integer & 0x0000ff00) >> 8) +
- chr((integer & 0x000000ff)))
+ return (chr((integer >> 24) & 0xff) +
+ chr((integer >> 16) & 0xff) +
+ chr((integer >> 8) & 0xff) +
+ chr((integer >> 0) & 0xff))
+
+def splitbits(integer, lengths):
+ assert sum(lengths) <= 32
+ result = []
+ for length in lengths:
+ result.append(integer & (2**length - 1))
+ integer = integer >> length
+ #XXX we can later mask and unroll this
+ return result
+
# ____________________________________________________________
#
@@ -26,6 +35,7 @@
self.count = 0
def peek(self):
+ import struct
if self.pos >= len(self.data):
raise IndexError
if self.swap:
@@ -49,15 +59,11 @@
assert (self.pos + jump) <= len(self.data)
self.pos += jump
self.count += jump
+
+ def close(self):
+ pass # already closed
+
-def splitbits(integer, lengths):
- assert sum(lengths) <= 32
- result = []
- for length in lengths:
- result.append(integer & (2**length - 1))
- integer = integer >> length
- #XXX we can later mask and unroll this
- return result
class CorruptImageError(Exception):
pass
@@ -73,24 +79,14 @@
self.read_body()
self.init_compactclassesarray()
self.init_g_objects()
-
- def init_g_objects(self):
- for chunk in self.chunks.itervalues():
- chunk.as_g_object(self)
-
- def init_w_objects(self):
- for chunk in self.chunks.itervalues():
- chunk.g_object.init_w_object()
+ self.init_w_objects()
+ self.fillin_w_objects()
- def fillin_w_objects(self):
- for chunk in self.chunks.itervalues():
- chunk.g_object.fillin_w_object()
-
def read_header(self):
version = self.stream.next()
- if version != 0x1966: raise NotImplementedError
+ if version != 0x1966: raise NotImplementedError #XXX swap here if 0x66190000
headersize = self.stream.next()
- self.endofmemory = self.stream.next()
+ self.endofmemory = self.stream.next() # endofmemory = bodysize
self.oldbaseaddress = self.stream.next()
self.specialobjectspointer = self.stream.next()
lasthash = self.stream.next()
@@ -98,16 +94,31 @@
fullscreenflag = self.stream.next()
extravmmemory = self.stream.next()
self.stream.skipbytes(headersize - (9 * 4))
-
+
def read_body(self):
self.chunks = {}
self.stream.reset_count()
while self.stream.count < self.endofmemory:
chunk, pos = self.read_object()
self.chunks[pos + self.oldbaseaddress] = chunk
- return self.chunks.values()
+ self.stream.close()
+ del self.stream
+ return self.chunks.values() # return for testing
+
+ def init_g_objects(self):
+ for chunk in self.chunks.itervalues():
+ chunk.as_g_object(self) # initialized g_object
+
+ def init_w_objects(self):
+ for chunk in self.chunks.itervalues():
+ chunk.g_object.init_w_object()
+
+ def fillin_w_objects(self):
+ for chunk in self.chunks.itervalues():
+ chunk.g_object.fillin_w_object()
def init_compactclassesarray(self):
+ """ (CompiledMethod Symbol Array PseudoContext LargePositiveInteger nil MethodDictionary Association Point Rectangle nil TranslatedMethod BlockContext MethodContext nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil ) """
special = self.chunks[self.specialobjectspointer]
assert special.size > 24 #at least
assert special.format == 2
@@ -116,10 +127,6 @@
assert chunk.format == 2
self.compactclasses = [self.chunks[pointer] for pointer in chunk.data]
- def init_actualobjects(self):
- for chunk in self.chunks.itervalues():
- chunk.get_actual() # initialization
-
def read_object(self):
kind = self.stream.peek() & 3 # 2 bits
if kind == 0: # 00 bits
@@ -142,8 +149,8 @@
return ImageChunk(size, format, classid, idhash), self.stream.count - 4
def read_2wordobjectheader(self):
- assert splitbits(self.stream.peek(), [2])[0] == 1 #kind
- classid = self.stream.next() - 1 # remove headertype to get pointer
+ assert self.stream.peek() & 3 == 1 #kind
+ classid = self.stream.next() - 01 # remove headertype to get pointer
kind, size, format, _, idhash = splitbits(self.stream.next(), [2,6,4,5,12])
assert kind == 1
return ImageChunk(size, format, classid, idhash), self.stream.count - 4
@@ -152,12 +159,28 @@
kind, size = splitbits(self.stream.next(), [2,30])
assert kind == 0
assert splitbits(self.stream.peek(), [2])[0] == 0 #kind
- classid = self.stream.next() - 0 # remove headertype to get pointer
+ classid = self.stream.next() - 00 # remove headertype to get pointer
kind, _, format, _, idhash = splitbits(self.stream.next(), [2,6,4,5,12])
assert kind == 0
return ImageChunk(size, format, classid, idhash), self.stream.count - 4
+
+# ____________________________________________________________
+
+class SqueakImage(object):
+
+ def from_reader(self, reader):
+ self.special_objects = [g_object.w_object for g_object in
+ reader.chunks[reader.specialobjectspointer]
+ .g_object.pointers]
+ self.objects = [chunk.g_object.w_object for chunk in reader.chunks.itervalues()]
+
+ def special(self, index):
+ return self.special_objects[index]
+
COMPACT_CLASSES_ARRAY = 28
+FLOAT_CLASS = 10
+
# ____________________________________________________________
@@ -177,7 +200,7 @@
self.owner = reader
self.value = value
self.size = -1
- self.w_object = fakeimage.small_int(value)
+ self.w_object = fakeimage.wrap_int(value)
def initialize(self, chunk, reader):
self.owner = reader
@@ -198,14 +221,15 @@
def init_data(self, chunk):
if not self.ispointers(): return
- self.pointers = []
- for pointer in chunk.data:
- g_object = self.decode_pointer(pointer)
- self.pointers.append(g_object)
+ self.pointers = [self.decode_pointer(pointer)
+ for pointer in chunk.data]
+ assert len(filter(lambda x: x is None, self.pointers)) == 0
def decode_pointer(self, pointer):
if (pointer & 1) == 1:
- return GenericObject().initialize_int(pointer >> 1, self.owner)
+ small_int = GenericObject()
+ small_int.initialize_int(pointer >> 1, self.owner)
+ return small_int
else:
return self.owner.chunks[pointer].g_object
@@ -219,8 +243,24 @@
return self.format < 5 #TODO, what about compiled methods?
def init_w_object(self):
+ """ 0 no fields
+ 1 fixed fields only (all containing pointers)
+ 2 indexable fields only (all containing pointers)
+ 3 both fixed and indexable fields (all containing pointers)
+ 4 both fixed and indexable weak fields (all containing pointers).
+
+ 5 unused
+ 6 indexable word fields only (no pointers)
+ 7 indexable long (64-bit) fields (only in 64-bit images)
+
+ 8-11 indexable byte fields only (no pointers) (low 2 bits are low 2 bits of size)
+ 12-15 compiled methods:
+ # of literal oops specified in method header,
+ followed by indexable bytes (same interpretation of low 2 bits as above)
+ """
if self.w_object is None:
if self.format < 5:
+ # XXX self.format == 4 is weak
self.w_object = objectmodel.instantiate(model.W_PointersObject)
elif self.format == 5:
raise CorruptImageError("Unknown format 5")
@@ -240,17 +280,21 @@
# below we are using an RPython idiom to 'cast' self.w_object
# and pass the casted reference to the fillin_* methods
casted = self.w_object
- case = type(casted)
+ case = casted.__class__
if case == model.W_PointersObject:
- self.fillin_poingersobject(casted)
+ self.fillin_pointersobject(casted)
elif case == model.W_WordsObject:
self.fillin_wordsobject(casted)
elif case == model.W_BytesObject:
self.fillin_bytesobject(casted)
elif case == model.W_CompiledMethod:
self.fillin_compiledmethod(casted)
+ else:
+ assert 0
+ assert casted.invariant()
def fillin_pointersobject(self, w_pointersobject):
+ assert self.pointers is not None
w_pointersobject.vars = [g_object.w_object for g_object in self.pointers]
w_pointersobject.w_class = self.g_class.w_object
@@ -260,16 +304,16 @@
def fillin_bytesobject(self, w_bytesobject):
bytes = []
- for each in chunk.data:
- bytes.append((integer & 0xff000000) >> 24)
- bytes.append((integer & 0xff000000) >> 16)
- bytes.append((integer & 0xff000000) >> 8)
- bytes.append((integer & 0xff000000))
+ for each in self.chunk.data:
+ bytes.append((each >> 24) & 0xff)
+ bytes.append((each >> 16) & 0xff)
+ bytes.append((each >> 8) & 0xff)
+ bytes.append((each >> 0) & 0xff)
w_bytesobject.w_class = self.g_class.w_object
w_bytesobject.bytes = bytes[:-(self.format & 3)] # omit odd bytes
def fillin_compiledmethod(self, w_compiledmethod):
- header = chunk.data[0]
+ header = self.chunk.data[0]
#(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)
@@ -277,18 +321,19 @@
#(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)
- highbit, numargs, tempsize, islarge, literalsize, primitive = (
- splitbits(header, [1,4,6,1,8,9]))
+ primitive, literalsize, islarge, tempsize, numargs, highbit = (
+ splitbits(header, [9,8,1,6,4,1]))
primitive = primitive + (highbit << 10)
- assert (1 + literalsize) < len(chunk.data)
+ #assert literalsize <= len(self.chunk.data)
l = []
- for each in chunk.data[(1 + literalsize):]:
+ for each in self.chunk.data[(1 + literalsize):]:
l.append(int2str(each))
- l[-1] = l[-1][:-(self.format & 3)] # omit odd bytes
+ if len(l) > 0:
+ l[-1] = l[-1][:-(self.format & 3)] # omit odd bytes
bytes = "".join(l)
w_compiledmethod.__init__(
w_class = self.g_class.w_object,
- size = self.literalsize,
+ size = literalsize,
bytes = bytes,
argsize = numargs,
tempsize = tempsize,
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 Wed Oct 24 17:49:17 2007
@@ -17,20 +17,6 @@
w_myinstance.setnamedvar(1, w_myinstance)
assert w_myinstance.getnamedvar(1) is w_myinstance
-def test_new_indexednamedvars():
- w_mycls = model.W_Class(None, None, 3, format=model.VAR_POINTERS)
- w_myinstance = w_mycls.new(2)
- assert isinstance(w_myinstance, model.W_PointersObject)
- assert w_myinstance.w_class is w_mycls
- assert w_myinstance.getnamedvar(0) is None
- py.test.raises(IndexError, lambda: w_myinstance.getnamedvar(3))
- w_myinstance.setnamedvar(1, w_myinstance)
- assert w_myinstance.getnamedvar(1) is w_myinstance
- assert w_myinstance.getindexedvar(1) is None
- py.test.raises(IndexError, lambda: w_myinstance.getindexedvar(2))
- w_myinstance.setindexedvar(0, w_myinstance)
- assert w_myinstance.getindexedvar(0) is w_myinstance
-
def test_bytes_object():
w_class = model.W_Class(None, None, format=model.BYTES)
w_bytes = w_class.new(20)
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 Wed Oct 24 17:49:17 2007
@@ -53,7 +53,7 @@
def test_at():
w_obj = model.W_Class(None, None, 0, format=model.VAR_POINTERS).new(1)
- w_obj.setindexedvar(0, "foo")
+ w_obj.store(0, "foo")
assert prim(p.AT, [w_obj, 0]) == "foo"
def test_invalid_at():
Modified: pypy/dist/pypy/lang/smalltalk/test/test_squeakimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_squeakimage.py (original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_squeakimage.py Wed Oct 24 17:49:17 2007
@@ -126,52 +126,3 @@
assert pos == 8
assert chunk0 == chunk
-# ----- mini.image productline -------------------------------
-# relying on order of methods
-
-mini_image = py.magic.autopath().dirpath().dirpath().join('mini.image')
-
-def test_miniimageexists():
- assert mini_image.check(dir=False)
-
-example = squeakimage.ImageReader(squeakimage.Stream(mini_image.open()))
-
-def test_read_header():
- example.read_header()
- assert example.endofmemory == 0x93174
- assert example.oldbaseaddress == 0x6649000
- assert example.specialobjectspointer == 0x6668380
-
-def test_read_all_header():
- next = example.stream.peek()
- assert next != 0 #expects object header, which must not be 0x00000000
-
-def test_read_body():
- objects = example.read_body()
- assert len(objects) > 0
- assert 15000 < len(objects) < 16000
-
-def test_read_all_body():
- py.test.raises(IndexError, lambda: example.stream.next())
-
-def test_all_pointers_valid():
- for each in example.chunks.itervalues():
- if each.format < 5:
- for pointer in each.data:
- if (pointer & 1) != 1:
- assert pointer in example.chunks
-
-def test_init_compactclasses():
- example.init_compactclassesarray()
- assert len(example.compactclasses) == 31
-
-def test_init_g_objects():
- example.init_g_objects()
-
-def test_init_w_objects():
- example.init_w_objects()
-
-def test_fillin_w_objects():
- example.fillin_w_objects()
-
-
\ No newline at end of file
More information about the pypy-svn
mailing list