[pypy-commit] lang-smalltalk storage: Refactored creation of context objects.

anton_gulenko noreply at buildbot.pypy.org
Tue Aug 5 18:06:40 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage
Changeset: r1010:d007ca0a7137
Date: 2014-08-05 17:54 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/d007ca0a7137/

Log:	Refactored creation of context objects. Created build() methods,
	clean up default constructor. This ensures that certain fields are
	only initialized once.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -278,7 +278,7 @@
         assert len(w_arguments) <= 7
         w_method.setbytes([chr(131), chr(len(w_arguments) << 5 + 0), chr(124)]) #returnTopFromMethodBytecode
         w_method.set_lookup_class_and_name(w_receiver.getclass(self.space), "Interpreter.perform")
-        s_frame = MethodContextShadow(self.space, w_method=w_method, w_receiver=w_receiver)
+        s_frame = MethodContextShadow.build(self.space, w_method, w_receiver)
         s_frame.push(w_receiver)
         s_frame.push_all(list(w_arguments))
         return s_frame
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -1269,7 +1269,7 @@
     def create_frame(self, space, receiver, arguments=[]):
         from spyvm.storage_contexts import MethodContextShadow
         assert len(arguments) == self.argsize
-        return MethodContextShadow(space, w_method=self, w_receiver=receiver, arguments=arguments)
+        return MethodContextShadow.build(space, self, receiver, arguments)
         
     # === Printing ===
 
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -1287,12 +1287,12 @@
     # context of the receiver is used for the new BlockContext.
     # Note that in our impl, MethodContext.w_home == self
     w_context = assert_pointers(w_context)
-    w_method_context = w_context.as_context_get_shadow(interp.space).s_home().w_self()
+    s_method_context = w_context.as_context_get_shadow(interp.space).s_home()
 
     # The block bytecodes are stored inline: so we skip past the
-    # byteodes to invoke this primitive to find them (hence +2)
+    # bytecodes to invoke this primitive to get to them.
     initialip = s_frame.pc() + 2
-    s_new_context = storage_contexts.BlockContextShadow(interp.space, None, 0, w_method_context, argcnt, initialip)
+    s_new_context = storage_contexts.BlockContextShadow.build(interp.space, s_method_context, argcnt, initialip)
     return s_new_context.w_self()
 
 @expose_primitive(VALUE, result_is_new_frame=True)
diff --git a/spyvm/storage_contexts.py b/spyvm/storage_contexts.py
--- a/spyvm/storage_contexts.py
+++ b/spyvm/storage_contexts.py
@@ -2,8 +2,11 @@
 from spyvm import model, constants, error, wrapper
 from spyvm.storage import AbstractRedirectingShadow
 from rpython.tool.pairtype import extendabletype
-from rpython.rlib import rarithmetic, jit
-from rpython.rlib.debug import make_sure_not_resized
+from rpython.rlib import rarithmetic, jit, objectmodel
+
+ at objectmodel.specialize.call_location()
+def fresh_virtualizable(x):
+    return jit.hint(x, access_directly=True, fresh_virtualizable=True)
 
 class ContextState(object):
     def __init__(self, name):
@@ -33,11 +36,12 @@
     # ______________________________________________________________________
     # Initialization
 
-    def __init__(self, space, w_self, size=0):
+    def __init__(self, space, w_self, size):
         self._s_sender = None
         AbstractRedirectingShadow.__init__(self, space, w_self, size)
         self.instances_w = {}
         self.state = InactiveContext
+        self.store_pc(0)
 
     def copy_from(self, other_shadow):
         # Some fields have to be initialized before the rest, to ensure correct initialization.
@@ -237,15 +241,15 @@
 
     @jit.unroll_safe
     def init_stack_and_temps(self):
+        self = fresh_virtualizable(self)
         stacksize = self.stackend() - self.stackstart()
         tempsize = self.tempsize()
         temps_and_stack = [None] * (stacksize + tempsize)
         self._temps_and_stack = temps_and_stack
-        make_sure_not_resized(temps_and_stack)
         for i in range(tempsize):
             temps_and_stack[i] = self.space.w_nil
         self._stack_ptr = rarithmetic.r_uint(tempsize) # we point after the last element
-
+    
     def stack_get(self, index0):
         return self._temps_and_stack[index0]
 
@@ -369,24 +373,29 @@
     repr_classname = "BlockContextShadow"
 
     # === Initialization ===
-
-    def __init__(self, space, w_self=None, size=0, w_home=None, argcnt=0, initialip=0):
-        self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
-        creating_w_self = w_self is None
-        if creating_w_self:
-            s_home = w_home.as_methodcontext_get_shadow(space)
-            contextsize = s_home.size() - s_home.tempsize()
-            w_self = model.W_PointersObject(space, space.w_BlockContext, contextsize)
+    
+    @staticmethod
+    def build(space, s_home, argcnt, pc):
+        size = s_home.size() - s_home.tempsize()
+        w_self = model.W_PointersObject(space, space.w_BlockContext, size)
+        
+        ctx = BlockContextShadow(space, w_self, size)
+        ctx.store_expected_argument_count(argcnt)
+        ctx.store_w_home(s_home.w_self())
+        ctx.store_initialip(pc)
+        ctx.store_pc(pc)
+        
+        w_self.store_shadow(ctx)
+        ctx.init_stack_and_temps()
+        return ctx
+    
+    def __init__(self, space, w_self, size):
+        self = fresh_virtualizable(self)
         ContextPartShadow.__init__(self, space, w_self, size)
-        if creating_w_self:
-            w_self.store_shadow(self)
-        self.store_expected_argument_count(argcnt)
-        self.store_initialip(initialip)
-        if w_home:
-            self.store_w_home(w_home)
-        self.store_pc(initialip)
-        self.init_stack_and_temps()
-
+        self._w_home = None
+        self._initialip = 0
+        self._eargc = 0
+    
     def fields_to_copy_first(self):
         return [ constants.BLKCTX_HOME_INDEX ]
 
@@ -502,37 +511,43 @@
     repr_classname = "MethodContextShadow"
 
     # === Initialization ===
-
+    
+    @staticmethod
+    def build(space, w_method, w_receiver, arguments=[], closure=None):
+        s_MethodContext = space.w_MethodContext.as_class_get_shadow(space)
+        size = w_method.compute_frame_size() + s_MethodContext.instsize()
+        
+        ctx = MethodContextShadow(space, None, size)
+        ctx.store_w_receiver(w_receiver)
+        ctx.store_w_method(w_method)
+        ctx.closure = closure
+        ctx.init_stack_and_temps()
+        ctx.initialize_temps(arguments)
+        return ctx
+    
+    def __init__(self, space, w_self, size):
+        self = fresh_virtualizable(self)
+        ContextPartShadow.__init__(self, space, w_self, size)
+        self.closure = None
+        self._w_method = None
+        self._w_receiver = None
+        self._is_BlockClosure_ensure = False
+    
+    def fields_to_copy_first(self):
+        return [ constants.MTHDCTX_METHOD, constants.MTHDCTX_CLOSURE_OR_NIL ]
+    
     @jit.unroll_safe
-    def __init__(self, space, w_self=None, size=0, w_method=None, w_receiver=None,
-                              arguments=[], closure=None, pc=0):
-        self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
-        ContextPartShadow.__init__(self, space, w_self, size)
-        self.store_w_receiver(w_receiver)
-        self.store_pc(pc)
-        self.closure = closure
-
-        if w_method:
-            self.store_w_method(w_method)
-            # The summand is needed, because we calculate i.a. our stackdepth relative of the size of w_self.
-            size = w_method.compute_frame_size() + self.space.w_MethodContext.as_class_get_shadow(self.space).instsize()
-            self._w_self_size = size
-            self.init_stack_and_temps()
-        else:
-            self._w_method = None
-            self._is_BlockClosure_ensure = False
-
+    def initialize_temps(self, arguments):
         argc = len(arguments)
         for i0 in range(argc):
             self.settemp(i0, arguments[i0])
-
+        closure = self.closure
         if closure:
+            pc = closure.startpc() - self.w_method().bytecodeoffset() - 1
+            self.store_pc(pc)
             for i0 in range(closure.size()):
                 self.settemp(i0+argc, closure.at0(i0))
-
-    def fields_to_copy_first(self):
-        return [ constants.MTHDCTX_METHOD, constants.MTHDCTX_CLOSURE_OR_NIL ]
-
+    
     # === Accessing object fields ===
 
     def fetch(self, n0):
@@ -593,9 +608,8 @@
     def store_w_method(self, w_method):
         assert isinstance(w_method, model.W_CompiledMethod)
         self._w_method = w_method
-        if w_method:
-            # Primitive 198 is used in BlockClosure >> ensure:
-            self._is_BlockClosure_ensure = (w_method.primitive() == 198)
+        # Primitive 198 is a marker used in BlockClosure >> ensure:
+        self._is_BlockClosure_ensure = (w_method.primitive() == 198)
 
     def w_receiver(self):
         return self._w_receiver
@@ -627,14 +641,10 @@
         if self._w_self is not None:
             return self._w_self
         else:
-            s_MethodContext = self.space.w_MethodContext.as_class_get_shadow(self.space)
-            size = self.size() - s_MethodContext.instsize()
             space = self.space
-            w_self = s_MethodContext.new(size)
-            assert isinstance(w_self, model.W_PointersObject)
+            w_self = model.W_PointersObject(space, space.w_MethodContext, self.size())
             w_self.store_shadow(self)
             self._w_self = w_self
-            self._w_self_size = w_self.size()
             return w_self
 
     # === Temporary variables ===
diff --git a/spyvm/test/jit.py b/spyvm/test/jit.py
--- a/spyvm/test/jit.py
+++ b/spyvm/test/jit.py
@@ -49,7 +49,7 @@
     w_method.literals = literals
     w_method.setbytes(bytes)
     w_receiver = stack[0]
-    s_frame = storage_contexts.MethodContextShadow(space, w_method=w_method, w_receiver=w_receiver)
+    s_frame = storage_contexts.MethodContextShadow.build(space, w_method, w_receiver)
     w_frame = s_frame.w_self()
     def interp_execute_frame():
         return interp.interpret_toplevel(w_frame)
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
@@ -31,7 +31,7 @@
 
     def as_blockcontext_get_shadow(self, space):
         if not isinstance(self.shadow, storage_contexts.BlockContextShadow):
-            self.shadow = storage_contexts.BlockContextShadow(space, self)
+            self.shadow = storage_contexts.BlockContextShadow(space, self, self.size())
         return self.shadow
 
 IMAGENAME = "anImage.image"
diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py
--- a/spyvm/wrapper.py
+++ b/spyvm/wrapper.py
@@ -248,9 +248,7 @@
         s_outerContext = w_outerContext.as_context_get_shadow(self.space)
         w_method = s_outerContext.w_method()
         w_receiver = s_outerContext.w_receiver()
-        pc = self.startpc() - w_method.bytecodeoffset() - 1
-        return storage_contexts.MethodContextShadow(self.space, w_method=w_method, w_receiver=w_receiver,
-                     arguments=arguments, closure=self, pc=pc)
+        return storage_contexts.MethodContextShadow.build(self.space, w_method, w_receiver, arguments, self)
 
     def tempsize(self):
         # We ignore the number of temps a block has, because the first


More information about the pypy-commit mailing list