Author: Lars Wassermann <[email protected]>
Branch: 
Changeset: r115:d950d90d00ce
Date: 2013-03-04 14:47 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/d950d90d00ce/

Log:    refactored the interpreter to build up a stack of c-frames, not of
        interpreters with c-frame refactored loop-implementation into the
        trampoline function loop and c_loop, which are somewhat equivalent
        to frames added test which checks the stack depth by inspecting the
        method names on the stack

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -26,10 +26,9 @@
     _w_last_active_context = None
     cnt = 0
     _last_indent = ""
-    _loop = True
     jit_driver = jit.JitDriver(
         greens=['pc', 'self', 'method'],
-        reds=['s_active_context'],
+        reds=['s_active_context', 'w_active_context'],
         get_printable_location=get_printable_location
     )
     
@@ -38,6 +37,7 @@
         self.image = image
         self.image_name = image_name
         self.max_stack_depth = max_stack_depth
+        self.stack_depth = max_stack_depth
         self._loop = False
 
     def interpret_with_w_frame(self, w_frame):
@@ -54,7 +54,17 @@
         return conftest.option.prim_trace
 
     def loop(self, w_active_context):
+        # just a trampoline for the actual loop implemented in c_loop
         self._loop = True
+        w_new_context = w_active_context
+        while True:
+            try:
+                w_new_context = self.c_loop(w_new_context)
+            except StackOverflow, e:
+                self.stack_depth = self.max_stack_depth
+                w_new_context = e.w_context
+
+    def c_loop(self, w_active_context):
         s_active_context = w_active_context.as_context_get_shadow(self.space)
         while True:
             pc = s_active_context._pc
@@ -62,14 +72,25 @@
 
             self.jit_driver.jit_merge_point(
                 pc=pc, self=self, method=method,
-                s_active_context=s_active_context)
-            try:
-                w_new_context = self.step(s_active_context)
-            except StackOverflow, e:
-                w_new_context = e.w_context
-            if w_new_context is not None:
-                # we return to the context mentioned -> mark all contexts in 
between as mark_returned
-                s_active_context = 
w_new_context.as_context_get_shadow(self.space)
+                s_active_context=s_active_context,
+                w_active_context=w_active_context)
+            w_return_to_context = self.step(s_active_context)
+            if (w_return_to_context is not None
+                    and not 
w_return_to_context.is_same_object(w_active_context)):
+                
w_active_context.as_context_get_shadow(self.space).mark_returned()
+                return w_return_to_context
+
+    def stack_frame(self, w_new_frame):
+        if not self._loop:
+            return w_new_frame # this test is done to not loop in test,
+                               # but rather step just once where wanted
+        if self.stack_depth == 1:
+            raise StackOverflow(w_new_frame)
+
+        self.stack_depth = self.stack_depth - 1
+        retval = self.c_loop(w_new_frame)
+        self.stack_depth = self.stack_depth + 1
+        return retval
 
     def perform(self, w_receiver, selector, *arguments_w):
         if isinstance(selector, str):
@@ -97,41 +118,6 @@
         except ReturnFromTopLevel, e:
             return e.object
 
-    def stack_frame(self, w_new_frame):
-        if not self._loop:
-            return w_new_frame # this test is done to not loop in test, 
-                               # but rather step just once where wanted
-        if self.max_stack_depth == 1:
-            raise StackOverflow(w_new_frame)
-        #method = s_active_context.w_method()
-        #print method.get_identifier_string()
-        interp = StackedInterpreter(self.space, self.image, self.image_name, 
-                                    self.max_stack_depth - 1)
-        return interp.loop(w_new_frame)
-
-class StackedInterpreter(Interpreter):
-    def __init__(self, space, image, image_name, max_stack_depth):
-        self.space = space
-        self.image = image
-        self.image_name = image_name
-        self.max_stack_depth = max_stack_depth
-
-    def loop(self, w_active_context):
-        s_active_context = w_active_context.as_context_get_shadow(self.space)
-        while True:
-            pc = s_active_context._pc
-            method = s_active_context.method()
-
-            self.jit_driver.jit_merge_point(
-                pc=pc, self=self, method=method,
-                s_active_context=s_active_context)
-            w_return_to_context = self.step(s_active_context)
-            if (w_return_to_context is not None 
-                    and w_return_to_context is not w_active_context):
-                assert w_return_to_context._shadow._w_sender is not 
w_active_context
-                
w_active_context.as_context_get_shadow(self.space).mark_returned()
-                return w_return_to_context
-
 class ReturnFromTopLevel(Exception):
     def __init__(self, object):
         self.object = object
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -636,6 +636,7 @@
         return 0
 
 class MethodContextShadow(ContextPartShadow):
+
     def __init__(self, space, w_self):
         self.w_closure_or_nil = space.w_nil
         self._w_receiver = None
@@ -757,10 +758,10 @@
             # XXX check whether we can actually return from that context
             if s_outerContext.pc() == -1:
                 raise error.BlockCannotReturnError()
-            return s_outerContext._return(self.top(), interp, 
-                                    s_outerContext.s_home().w_sender())
+            return_to_context = s_outerContext.s_home().w_sender()
         else:
-            return self._return(self.top(), interp, self.s_home().w_sender())
+            return_to_context = self.s_home().w_sender()
+        return self._return(self.top(), interp, return_to_context)
 
     def is_closure_context(self):
         return self.w_closure_or_nil is not self.space.w_nil
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
@@ -962,7 +962,7 @@
     #         ifFalse: [ (testBlock value: aNumber - 1) + aNumber ]].
     # ^ testBlock value: 11
     import operator
-    interp = interpreter.Interpreter(space, max_stack_depth=2)
+    interp = interpreter.Interpreter(space, max_stack_depth=3)
     #create a method with the correct bytecodes and a literal
     bytes = reduce(operator.add, map(chr, [0x8a, 0x01, 0x68, 0x10, 0x8f, 0x11, 
         0x00, 0x11, 0x10, 0x75, 0xb6, 0x9a, 0x75, 0xa4, 0x09, 0x8c, 0x00, 
0x01, 
@@ -984,9 +984,49 @@
     except interpreter.StackOverflow, e:
         assert False
     try:
-        interp = interpreter.StackedInterpreter(space, None, "", 10)
-        
interp.loop(w_method.as_compiledmethod_get_shadow(space).create_frame(space, 
space.wrap_int(0), []))
+        interp = interpreter.Interpreter(space, None, "", max_stack_depth=10)
+        
interp.c_loop(w_method.as_compiledmethod_get_shadow(space).create_frame(space, 
space.wrap_int(0), []))
     except interpreter.StackOverflow, e:
         assert e.w_context.getclass(space) is space.w_MethodContext
     except interpreter.ReturnFromTopLevel, e:
+        assert False
+
+class StackTestInterpreter(interpreter.Interpreter):
+    def stack_frame(self, w_frame):
+        import sys
+        stack_depth = self.max_stack_depth - self.stack_depth
+        for i in range(stack_depth + 1):
+            assert sys._getframe(4 + i * 6).f_code.co_name == 'c_loop'
+        assert sys._getframe(5 + stack_depth * 6).f_code.co_name == 'loop'
+        return interpreter.Interpreter.stack_frame(self, w_frame)
+
+def test_actual_stackdepth():
+    # | testBlock |
+    # testBlock := [ :aNumber |
+    #     aNumber = 0
+    #         ifTrue: [ 2 ]
+    #         ifFalse: [ (testBlock value: aNumber - 1) + aNumber ]].
+    # ^ testBlock value: 11
+    import operator
+    interp = StackTestInterpreter(space, max_stack_depth=10)
+    #create a method with the correct bytecodes and a literal
+    bytes = reduce(operator.add, map(chr, [0x8a, 0x01, 0x68, 0x10, 0x8f, 0x11,
+        0x00, 0x11, 0x10, 0x75, 0xb6, 0x9a, 0x77, 0xa4, 0x09, 0x8c, 0x00, 0x01,
+        0x10, 0x76, 0xb1, 0xca, 0x10, 0xb0, 0x7d, 0x8e, 0x00, 0x00, 0x8c, 0x00,
+        0x00, 0x20, 0xca, 0x7c]))
+
+    w_method = model.W_CompiledMethod(len(bytes))
+    w_method.islarge = 1
+    w_method.bytes = bytes
+    w_method.argsize=0
+    w_method.tempsize=1
+    w_method.setliterals([space.wrap_int(11)])
+
+    #create a frame for that method
+    w_frame = w_method.as_compiledmethod_get_shadow(space).create_frame(space, 
space.wrap_int(0), [])
+    try:
+        interp.loop(w_frame)
+    except interpreter.ReturnFromTopLevel, e:
+        assert space.unwrap_int(e.object) == 68
+    except interpreter.StackOverflow, e:
         assert False
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to