[pypy-commit] lang-smalltalk storage: Removed virtual reference of sender. Was causing performance problems.

anton_gulenko noreply at buildbot.pypy.org
Thu Jul 10 12:56:58 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage
Changeset: r880:4934d77ae183
Date: 2014-07-10 12:38 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/4934d77ae183/

Log:	Removed virtual reference of sender. Was causing performance
	problems. Going to add this refactoring to the vref branch.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -67,10 +67,7 @@
         s_new_context = w_active_context.as_context_get_shadow(self.space)
         while True:
             assert self.current_stack_depth == 0
-            # Need to save s_sender, loop_bytecodes will nil this on return
-            # Virtual references are not allowed here, and neither are "fresh" contexts (except for the toplevel one).
-            assert s_new_context.virtual_sender is jit.vref_None
-            s_sender = s_new_context.direct_sender
+            s_sender = s_new_context.s_sender()
             try:
                 self.loop_bytecodes(s_new_context)
                 raise Exception("loop_bytecodes left without raising...")
@@ -81,7 +78,7 @@
             except Return, nlr:
                 s_new_context = s_sender
                 while s_new_context is not nlr.s_target_context:
-                    s_sender = s_new_context.direct_sender
+                    s_sender = s_new_context.s_sender()
                     s_new_context._activate_unwind_context(self)
                     s_new_context = s_sender
                 s_new_context.push(nlr.value)
@@ -122,27 +119,19 @@
     # This is a wrapper around loop_bytecodes that cleanly enters/leaves the frame
     # and handles the stack overflow protection mechanism.
     def stack_frame(self, s_frame, s_sender, may_context_switch=True):
-        assert s_frame.virtual_sender is jit.vref_None
         try:
-            # Enter the context - store a virtual reference back to the sender
-            # Non-fresh contexts can happen, e.g. when activating a stored BlockContext.
-            # The same frame object must not pass through here recursively!
-            if s_frame.is_fresh() and s_sender is not None:
-                s_frame.virtual_sender = jit.virtual_ref(s_sender)
-
+            if s_frame._s_sender is None and s_sender is not None:
+                s_frame.store_s_sender(s_sender, raise_error=False)
+            
             self.current_stack_depth += 1
             if self.max_stack_depth > 0:
                 if self.current_stack_depth >= self.max_stack_depth:
                     raise StackOverflow(s_frame)
-
+            
             # Now (continue to) execute the context bytecodes
             self.loop_bytecodes(s_frame, may_context_switch)
         finally:
             self.current_stack_depth -= 1
-            # Cleanly leave the context. This will finish the virtual sender-reference, if
-            # it is still there, which can happen in case of ProcessSwitch or StackOverflow;
-            # in case of a Return, this will already be handled while unwinding the stack.
-            s_frame.finish_virtual_sender(s_sender)
 
     def step(self, context):
         bytecode = context.fetch_next_bytecode()
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -607,13 +607,13 @@
 class ContextPartShadow(AbstractRedirectingShadow):
 
     __metaclass__ = extendabletype
-    _attrs_ = ['direct_sender', 'virtual_sender',
+    _attrs_ = ['_s_sender',
             '_pc', '_temps_and_stack',
             '_stack_ptr', 'instances_w']
     repr_classname = "ContextPartShadow"
 
     _virtualizable_ = [
-        'direct_sender', 'virtual_sender',
+        '_s_sender',
         "_pc", "_temps_and_stack[*]", "_stack_ptr",
         "_w_self", "_w_self_size"
     ]
@@ -622,8 +622,7 @@
     # Initialization
 
     def __init__(self, space, w_self):
-        self.direct_sender = None
-        self.virtual_sender = jit.vref_None
+        self._s_sender = None
         AbstractRedirectingShadow.__init__(self, space, w_self)
         self.instances_w = {}
 
@@ -692,27 +691,9 @@
             raise error.WrapperException("Index in context out of bounds")
 
     # === Sender ===
-    # There are two fields for the sender (virtual and direct). Only one of them is can be set at a time.
-    # As long as the frame object is virtualized, using the virtual reference should increase performance.
-    # As soon as a frame object is forced to the heap, the direct reference must be used.
-
-    def is_fresh(self):
-        return self.direct_sender is None and self.virtual_sender is jit.vref_None
-
-    def finish_virtual_sender(self, s_sender):
-        if self.virtual_sender is not jit.vref_None:
-            if self.pc() != -1:
-                # stack is unrolling, but this frame was not
-                # marked_returned: it is an escaped frame
-                sender = self.virtual_sender()
-                self.direct_sender = sender
-            jit.virtual_ref_finish(self.virtual_sender, s_sender)
-            self.virtual_sender = jit.vref_None
 
     def store_s_sender(self, s_sender, raise_error=True):
-        # If we have a virtual back reference, we must finish it before storing the direct reference.
-        # self.finish_virtual_sender(save_direct_sender=False)
-        self.direct_sender = s_sender
+        self._s_sender = s_sender
         if raise_error:
             raise error.SenderChainManipulation(self)
 
@@ -723,11 +704,7 @@
         return sender.w_self()
 
     def s_sender(self):
-        if self.direct_sender:
-            return self.direct_sender
-        else:
-            result = self.virtual_sender()
-            return result
+        return self._s_sender
 
     # === Stack Pointer ===
 


More information about the pypy-commit mailing list