Author: Anton Gulenko <[email protected]>
Branch: storage
Changeset: r702:5d8e0a95e3f9
Date: 2014-03-26 15:41 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/5d8e0a95e3f9/

Log:    Cleaned up bootstrapping of ObjSpace and especially
        BootstrappedObjSpace for tests. Tests now selectively bootstrap the
        ObjSpace only if they require the core classes. This way, many tests
        work with the real, non-bootstrapped, ObjSpace.

diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -41,17 +41,25 @@
         assert i > 0
         self._executable_path[0] = fullpath[:i]
 
+    def populate_special_objects(self, specials):
+        for name, idx in constants.objects_in_special_object_table.items():
+            name = "w_" + name
+            if not name in self.objtable or not self.objtable[name]:
+                self.add_bootstrap_object(name, specials[idx])
+        
     def executable_path(self):
         return self._executable_path[0]
-        
+    
+    def add_bootstrap_class(self, name, cls):
+        self.classtable[name] = cls
+        setattr(self, name, cls)
+    
     def make_bootstrap_classes(self):
         names = [ "w_" + name for name in 
constants.classes_in_special_object_table.keys() ]
         for name in names:
             cls = model.W_PointersObject(self, None, 0)
-            self.classtable[name] = cls
-            setattr(self, name, cls)
-                # Make sure that all prebuilt classes are actually used in the 
special classes array
-    
+            self.add_bootstrap_class(name, cls)
+        
     def add_bootstrap_object(self, name, obj):
         self.objtable[name] = obj
         setattr(self, name, obj)
@@ -60,15 +68,7 @@
         obj = model.W_PointersObject(self, None, 0)
         self.add_bootstrap_object(name, obj)
     
-    def make_bootstrap_objects(self):
-        self.make_bootstrap_object("w_true")
-        self.make_bootstrap_object("w_false")
-        self.make_bootstrap_object("w_special_selectors")
-        self.add_bootstrap_object("w_minus_one", model.W_SmallInteger(-1))
-        self.add_bootstrap_object("w_zero", model.W_SmallInteger(0))
-        self.add_bootstrap_object("w_one", model.W_SmallInteger(1))
-        self.add_bootstrap_object("w_two", model.W_SmallInteger(2))
-        
+    def make_character_table(self):
         def build_char(i):
             # TODO - This is pretty hacky, maybe not required? At least 
eliminate the constant 1.
             w_cinst = model.W_PointersObject(self, self.w_Character, 1)
@@ -79,12 +79,24 @@
         for i in range(256):
             char_table.store(self, i, build_char(i))
         self.add_bootstrap_object("w_charactertable", char_table)
+    
+    def make_bootstrap_objects(self):
+        self.make_character_table()
+        self.make_bootstrap_object("w_true")
+        self.make_bootstrap_object("w_false")
+        self.make_bootstrap_object("w_special_selectors")
+        self.add_bootstrap_object("w_minus_one", model.W_SmallInteger(-1))
+        self.add_bootstrap_object("w_zero", model.W_SmallInteger(0))
+        self.add_bootstrap_object("w_one", model.W_SmallInteger(1))
+        self.add_bootstrap_object("w_two", model.W_SmallInteger(2))
         
+        # Certain special objects are already created. The rest will be
+        # populated when the image is loaded, but prepare empty slots for them.
         for name in constants.objects_in_special_object_table:
             name = "w_" + name
             if not name in self.objtable:
                 self.add_bootstrap_object(name, None)
-
+    
     @specialize.arg(1)
     def get_special_selector(self, selector):
         i0 = constants.find_selectorindex(selector)
diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py
--- a/spyvm/squeakimage.py
+++ b/spyvm/squeakimage.py
@@ -370,10 +370,7 @@
         self.special_objects = [g_object.w_object for g_object in
                                 reader.chunks[reader.specialobjectspointer]
                                 .g_object.pointers]
-        
-        for name, idx in constants.objects_in_special_object_table.items():
-            space.objtable["w_" + name] = self.special_objects[idx]
-        
+        space.populate_special_objects(self.special_objects)
         self.w_asSymbol = self.find_symbol(space, reader, "asSymbol")
         self.w_simulateCopyBits = self.find_symbol(space, reader, 
"simulateCopyBits")
         self.lastWindowSize = reader.lastWindowSize
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
@@ -5,7 +5,7 @@
 from spyvm.conftest import option
 
 def setup_module():
-    space, interp = create_space_interp()
+    space, interp = create_space_interp(bootstrap = True)
     copy_to_module(locals(), __name__)
 
 def teardown_module():
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,7 +6,7 @@
 from .util import create_space, copy_to_module, cleanup_module
 
 def setup_module():
-    space = create_space()
+    space = create_space(bootstrap = True)
     bootstrap_class = space.bootstrap_class
     w_foo = space.wrap_string("foo")
     w_bar = space.wrap_string("bar")
diff --git a/spyvm/test/test_objectspace.py b/spyvm/test/test_objectspace.py
--- a/spyvm/test/test_objectspace.py
+++ b/spyvm/test/test_objectspace.py
@@ -4,7 +4,7 @@
 from .util import create_space, copy_to_module, cleanup_module
 
 def setup_module():
-    space = create_space()
+    space = create_space(bootstrap = True)
     copy_to_module(locals(), __name__)
 
 def teardown_module():
diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py
--- a/spyvm/test/test_primitives.py
+++ b/spyvm/test/test_primitives.py
@@ -9,7 +9,7 @@
 from .test_interpreter import _new_frame
 
 def setup_module():
-    space = create_space()
+    space = create_space(bootstrap = True)
     wrap = space.w
     bootstrap_class = space.bootstrap_class
     copy_to_module(locals(), __name__)
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
@@ -4,7 +4,7 @@
 from test_model import joinbits
 
 def setup_module():
-    space = create_space()
+    space = create_space(bootstrap = True)
     w_Object     = space.classtable['w_Object']
     w_Metaclass  = space.classtable['w_Metaclass']
     w_MethodDict = space.classtable['w_MethodDict']
diff --git a/spyvm/test/util.py b/spyvm/test/util.py
--- a/spyvm/test/util.py
+++ b/spyvm/test/util.py
@@ -2,13 +2,17 @@
 from spyvm import model, shadow, objspace, version, constants, squeakimage, 
interpreter
 from rpython.rlib.objectmodel import instantiate
 
+# Most tests don't need a bootstrapped objspace. Those that do, indicate so 
explicitely.
+# This way, as many tests as possible use the real, not-bootstrapped ObjSpace.
+bootstrap_by_default = False
+
 def open_reader(space, imagefilename):
     from spyvm.tool.analyseimage import image_dir
     imagefilename = image_dir.join(imagefilename)
     return squeakimage.reader_for_image(space, 
squeakimage.Stream(imagefilename.open(mode="rb")))
 
-def read_image(image_filename):
-    space = create_space()
+def read_image(image_filename, bootstrap = bootstrap_by_default):
+    space = create_space(bootstrap)
     reader = open_reader(space, image_filename)
     reader.initialize()
     image = squeakimage.SqueakImage()
@@ -16,11 +20,14 @@
     interp = interpreter.Interpreter(space, image)
     return space, interp, image, reader
 
-def create_space():
-    return BootstrappedObjSpace()
+def create_space(bootstrap = bootstrap_by_default):
+    space = BootstrappedObjSpace()
+    if bootstrap:
+        space.bootstrap()
+    return space
 
-def create_space_interp():
-    space = create_space()
+def create_space_interp(bootstrap = bootstrap_by_default):
+    space = create_space(bootstrap)
     interp = interpreter.Interpreter(space)
     return space, interp
 
@@ -49,29 +56,20 @@
 
 class BootstrappedObjSpace(objspace.ObjSpace):
     
-    def w(self, any):
-        if any is None: return self.w_nil
-        if isinstance(any, model.W_Object): return any
-        if isinstance(any, str):
-            # assume never have strings of length 1
-            if len(any) == 1:
-                return self.wrap_char(any)
-            else:
-                return self.wrap_string(any)
-        if isinstance(any, bool): return self.wrap_bool(any)
-        if isinstance(any, int): return self.wrap_int(any)
-        if isinstance(any, float): return self.wrap_float(any)
-        if isinstance(any, list): return self.wrap_list(any)
-        raise Exception("Cannot wrap %r" % any)
+    def bootstrap(self):
+        # Fill this ObjSpace up with class complete core hierarchies and patch 
core objects.
+        self.create_core_classes()
+        self.patch_bootstrap_classes()
+        self.patch_bootstrap_objects()
     
-    def make_bootstrap_classes(self):
+    def create_core_classes(self):
         def define_core_cls(name, w_superclass, w_metaclass):
             assert name.startswith('w_')
             w_class = self.bootstrap_class(instsize=0,    # XXX
                                       w_superclass=w_superclass,
                                       w_metaclass=w_metaclass,
                                       name=name[2:])
-            self.classtable[name] = w_class
+            self.add_bootstrap_class(name, w_class)
             return w_class
 
         #   A complete minimal setup (including Behavior) would look like this
@@ -105,111 +103,95 @@
             meta_super_nm = super_cls_nm + "Class"
             w_metacls = define_core_cls(meta_nm, 
self.classtable[meta_super_nm], None)
             define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls)
-        w_Class = self.classtable["w_Class"]
-        w_Metaclass = self.classtable["w_Metaclass"]
-        # XXX
         proto_shadow = w_ProtoObjectClass.shadow
-        proto_shadow.store_w_superclass(w_Class)
-        # at this point, all classes that still lack a w_class are themselves
-        # metaclasses
+        proto_shadow.store_w_superclass(self.w_Class)
+        # at this point, all classes that still lack a w_class are themselves 
metaclasses
         for nm, w_cls_obj in self.classtable.items():
             if w_cls_obj.w_class is None:
-                w_cls_obj.w_class = w_Metaclass
-
-        def define_cls(cls_nm, supercls_nm, instvarsize=0, 
format=shadow.POINTERS,
-                       varsized=False):
-            assert cls_nm.startswith("w_")
+                w_cls_obj.w_class = self.w_Metaclass
+    
+    def patch_bootstrap_classes(self):
+        # Create all classes in the class hierarchies of the classes in the 
special objects array.
+        def create_metaclass(cls_nm, supercls_nm):
             meta_nm = cls_nm + "Class"
             meta_super_nm = supercls_nm + "Class"
-            w_Metaclass = self.classtable["w_Metaclass"]
-            w_meta_cls = self.classtable[meta_nm] = \
-                         self.bootstrap_class(0,   # XXX
+            w_meta_cls = self.bootstrap_class(0,   # XXX
                                          self.classtable[meta_super_nm],
-                                         w_Metaclass,
+                                         self.w_Metaclass,
                                          name=meta_nm[2:])
-            w_cls = self.classtable[cls_nm] = \
-                         self.bootstrap_class(instvarsize,
+            self.add_bootstrap_class(meta_nm, w_meta_cls)
+            return w_meta_cls
+        def define_cls(cls_nm, supercls_nm, instvarsize=0, 
format=shadow.POINTERS, varsized=False):
+            assert cls_nm.startswith("w_")
+            w_meta_cls = create_metaclass(cls_nm, supercls_nm)
+            w_cls = self.bootstrap_class(instvarsize,
                                          self.classtable[supercls_nm],
                                          w_meta_cls,
                                          format=format,
                                          varsized=varsized,
                                          name=cls_nm[2:])
-
+            self.add_bootstrap_class(cls_nm, w_cls)
+            return w_cls
         define_cls("w_Magnitude", "w_Object")
-        define_cls("w_Character", "w_Magnitude", instvarsize=1)
         define_cls("w_Number", "w_Magnitude")
         define_cls("w_Integer", "w_Number")
-        define_cls("w_SmallInteger", "w_Integer")
-        define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES)
-        define_cls("w_Float", "w_Number", format=shadow.BYTES)
-        define_cls("w_Message", "w_Object")
         define_cls("w_Collection", "w_Object")
         define_cls("w_SequenceableCollection", "w_Collection")
         define_cls("w_ArrayedCollection", "w_SequenceableCollection")
-        define_cls("w_Array", "w_ArrayedCollection", varsized=True)
-        define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES)
-        define_cls("w_Bitmap", "w_ArrayedCollection", varsized=True, 
format=shadow.WORDS)
+        define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True)
+        define_cls("w_ContextPart", "w_Object")
+        define_cls("w_Link", "w_Object")
+        define_cls("w_LinkedList", "w_SequenceableCollection")
+        
+        # Also create classes for the objects in the special objects array
         define_cls("w_UndefinedObject", "w_Object")
         define_cls("w_Boolean", "w_Object")
         define_cls("w_True", "w_Boolean")
         define_cls("w_False", "w_Boolean")
-        define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES)
-        define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True)
-        define_cls("w_CompiledMethod", "w_ByteArray", 
format=shadow.COMPILED_METHOD)
-        define_cls("w_ContextPart", "w_Object")
-        define_cls("w_MethodContext", "w_ContextPart")
-        define_cls("w_Link", "w_Object")
-        define_cls("w_Process", "w_Link")
-        define_cls("w_Point", "w_Object")
-        define_cls("w_LinkedList", "w_SequenceableCollection")
-        define_cls("w_Semaphore", "w_LinkedList")
-        define_cls("w_BlockContext", "w_ContextPart",
-                   instvarsize=constants.BLKCTX_STACK_START)
-        define_cls("w_BlockClosure", "w_Object",
-                   instvarsize=constants.BLKCLSR_SIZE,
-                   varsized=True)
-        # make better accessors for classes that can be found in special object
-        # table
-        for name in constants.classes_in_special_object_table.keys():
-            name = 'w_' + name
-            setattr(self, name, self.classtable.get(name))
+        
+        # Now patch up the already created special classes
+        def patch_special_cls(cls_nm, supercls_nm, instvarsize=0, 
format=shadow.POINTERS, varsized=False):
+            assert cls_nm.startswith("w_")
+            w_meta_cls = create_metaclass(cls_nm, supercls_nm)
+            
+            # Now patch up the existing class object
+            w_cls = self.classtable[cls_nm]
+            assert w_cls, "This class should have been created in ObjSpace!"
+            self.patch_class(w_cls,
+                        instvarsize,
+                        self.classtable[supercls_nm],
+                        w_meta_cls,
+                        format=format,
+                        varsized=varsized,
+                        name=cls_nm[2:])
+        patch_special_cls("w_Bitmap", "w_ArrayedCollection", varsized=True, 
format=shadow.WORDS) 
+        patch_special_cls("w_SmallInteger", "w_Integer")
+        patch_special_cls("w_String", "w_ArrayedCollection", 
format=shadow.BYTES)
+        patch_special_cls("w_Array", "w_ArrayedCollection", varsized=True)
+        patch_special_cls("w_Float", "w_Number", format=shadow.BYTES)
+        patch_special_cls("w_MethodContext", "w_ContextPart")
+        patch_special_cls("w_BlockContext", "w_ContextPart", 
instvarsize=constants.BLKCTX_STACK_START)
+        patch_special_cls("w_BlockClosure", "w_Object", 
instvarsize=constants.BLKCLSR_SIZE, varsized=True)
+        patch_special_cls("w_Point", "w_Object")
+        patch_special_cls("w_LargePositiveInteger", "w_Integer", 
format=shadow.BYTES)
+        patch_special_cls("w_Message", "w_Object")
+        patch_special_cls("w_ByteArray", "w_ArrayedCollection", 
format=shadow.BYTES)
+        patch_special_cls("w_CompiledMethod", "w_ByteArray", 
format=shadow.COMPILED_METHOD)
+        patch_special_cls("w_Semaphore", "w_LinkedList")
+        patch_special_cls("w_Character", "w_Magnitude", instvarsize=1)
+        patch_special_cls("w_Process", "w_Link")
+        
+    def patch_bootstrap_objects(self):
+        def patch_bootstrap_object(obj, cls, size):
+            obj.w_class = cls
+            obj.initialize_storage(self, size)
+        patch_bootstrap_object(self.w_nil, self.w_UndefinedObject, 0)
+        patch_bootstrap_object(self.w_true, self.w_True, 0)
+        patch_bootstrap_object(self.w_false, self.w_False, 0)
+        patch_bootstrap_object(self.w_special_selectors, self.w_Array, 
len(constants.SPECIAL_SELECTORS) * 2)
 
-    def make_bootstrap_objects(self):
-        def bld_char(i):
-            w_cinst = self.w_Character.as_class_get_shadow(self).new()
-            w_cinst.store(self, constants.CHARACTER_VALUE_INDEX,
-                          model.W_SmallInteger(i))
-            return w_cinst
-        w_charactertable = model.W_PointersObject(self, 
self.classtable['w_Array'], 256)
-        self.add_bootstrap_object("w_charactertable", w_charactertable)
-        for i in range(256):
-            self.w_charactertable.atput0(self, i, bld_char(i))
-
-        # w_nil is already added to objtable in constructor.
-        self.w_nil.w_class = self.classtable['w_UndefinedObject']
-        self.w_nil.initialize_storage(self, 0)
-        
-        w_true = self.classtable['w_True'].as_class_get_shadow(self).new()
-        self.add_bootstrap_object("w_true", w_true)
-        w_false = self.classtable['w_False'].as_class_get_shadow(self).new()
-        self.add_bootstrap_object("w_false", w_false)
-        
-        self.add_bootstrap_object("w_minus_one", model.W_SmallInteger(-1))
-        self.add_bootstrap_object("w_zero", model.W_SmallInteger(0))
-        self.add_bootstrap_object("w_one", model.W_SmallInteger(1))
-        self.add_bootstrap_object("w_two", model.W_SmallInteger(2))
-        w_special_selectors = model.W_PointersObject(self,
-            self.classtable['w_Array'], len(constants.SPECIAL_SELECTORS) * 2)
-        self.add_bootstrap_object("w_special_selectors", w_special_selectors)
-        
-        for name in constants.objects_in_special_object_table:
-            name = "w_" + name
-            if not name in self.objtable:
-                self.add_bootstrap_object(name, None)
-
-    def bootstrap_class(self, instsize, w_superclass=None, w_metaclass=None,
+    def patch_class(self, w_class, instsize, w_superclass=None, 
w_metaclass=None,
                         name='?', format=shadow.POINTERS, varsized=False):
-        w_class = model.W_PointersObject(self, w_metaclass, 0)
         s = instantiate(shadow.ClassShadow)
         s.space = self
         s.version = version.Version()
@@ -223,8 +205,29 @@
         s._s_methoddict = None
         s.instance_varsized = varsized or format != shadow.POINTERS
         w_class.store_shadow(s)
+        w_class.w_class = w_metaclass
+        
+    def bootstrap_class(self, instsize, w_superclass=None, w_metaclass=None,
+                        name='?', format=shadow.POINTERS, varsized=False):
+        w_class = model.W_PointersObject(self, w_metaclass, 0)
+        self.patch_class(w_class, instsize, w_superclass, w_metaclass, name, 
format, varsized)
         return w_class
 
+    def w(self, any):
+        if any is None: return self.w_nil
+        if isinstance(any, model.W_Object): return any
+        if isinstance(any, str):
+            # assume never have strings of length 1
+            if len(any) == 1:
+                return self.wrap_char(any)
+            else:
+                return self.wrap_string(any)
+        if isinstance(any, bool): return self.wrap_bool(any)
+        if isinstance(any, int): return self.wrap_int(any)
+        if isinstance(any, float): return self.wrap_float(any)
+        if isinstance(any, list): return self.wrap_list(any)
+        raise Exception("Cannot wrap %r" % any)
+    
     def initialize_class(self, w_class, interp):
         initialize_symbol = find_symbol_in_methoddict_of("initialize", 
                             w_class.class_shadow(self))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to