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