[pypy-commit] lang-smalltalk storage-refactoring-virtual-pc: Merged storage branch.

anton_gulenko noreply at buildbot.pypy.org
Thu May 15 12:40:35 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage-refactoring-virtual-pc
Changeset: r830:a8514605c0c4
Date: 2014-05-15 12:40 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/a8514605c0c4/

Log:	Merged storage branch.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -25,7 +25,7 @@
 class Interpreter(object):
     _immutable_fields_ = ["space", "image", "image_name",
                           "max_stack_depth", "interrupt_counter_size",
-                          "startup_time", "evented"]
+                          "startup_time", "evented", "interrupts"]
     
     jit_driver = jit.JitDriver(
         greens=['pc', 'self', 'method'],
@@ -34,9 +34,9 @@
         get_printable_location=get_printable_location
     )
 
-    def __init__(self, space, image=None, image_name="", trace=False,
-                 evented=True,
-                 max_stack_depth=constants.MAX_LOOP_DEPTH):
+    def __init__(self, space, image=None, image_name="",
+                trace=False, evented=True, interrupts=True,
+                max_stack_depth=constants.MAX_LOOP_DEPTH):
         import time
         
         # === Initialize immutable variables
@@ -49,6 +49,7 @@
             self.startup_time = constants.CompileTime
         self.max_stack_depth = max_stack_depth
         self.evented = evented
+        self.interrupts = interrupts
         try:
             self.interrupt_counter_size = int(os.environ["SPY_ICS"])
         except KeyError:
@@ -56,7 +57,7 @@
         
         # === Initialize mutable variables
         self.interrupt_check_counter = self.interrupt_counter_size
-        self.remaining_stack_depth = max_stack_depth
+        self.current_stack_depth = 0
         self.next_wakeup_tick = 0
         self.trace = trace
         self.trace_proxy = False
@@ -65,13 +66,15 @@
         # This is the top-level loop and is not invoked recursively.
         s_new_context = w_active_context.as_context_get_shadow(self.space)
         while True:
-            assert self.remaining_stack_depth == self.max_stack_depth
+            assert self.current_stack_depth == 0
             # Need to save s_sender, loop_bytecodes will nil this on return
             s_sender = s_new_context.s_sender()
             try:
                 self.loop_bytecodes(s_new_context)
                 raise Exception("loop_bytecodes left without raising...")
             except StackOverflow, e:
+                if self.trace:
+                    print "====== StackOverflow, contexts forced to heap at: %s" % e.s_new_context.short_str()
                 s_new_context = e.s_new_context
             except Return, nlr:
                 s_new_context = s_sender
@@ -106,16 +109,26 @@
                     self.jitted_check_for_interrupt(s_context)
                 self.jit_driver.can_enter_jit(pc=pc, self=self, method=method, s_context=s_context)
     
-    # This is just a wrapper around loop_bytecodes that handles the remaining_stack_depth mechanism
+            try:
+                self.step(s_context)
+            except Return, nlr:
+                if nlr.s_target_context is not s_context:
+                    s_context._activate_unwind_context(self)
+                    raise nlr
+                else:
+                    s_context.push(nlr.value)
+    
+    # This is just a wrapper around loop_bytecodes that handles the stack overflow protection mechanism
     def stack_frame(self, s_new_frame, may_context_switch=True, fresh_context=False):
-        if self.remaining_stack_depth <= 1:
-            raise StackOverflow(s_new_frame)
-
-        self.remaining_stack_depth -= 1
+        if self.max_stack_depth > 0:
+            if self.current_stack_depth >= self.max_stack_depth:
+                raise StackOverflow(s_new_frame)
+        
+        self.current_stack_depth += 1
         try:
             self.loop_bytecodes(s_new_frame, may_context_switch=may_context_switch, fresh_context=fresh_context)
         finally:
-            self.remaining_stack_depth += 1
+            self.current_stack_depth -= 1
     
     def step(self, context, pc):
         bytecode = context.fetch_bytecode(pc)
@@ -134,6 +147,8 @@
     # ============== Methods for handling user interrupts ==============
     
     def jitted_check_for_interrupt(self, s_frame):
+        if not self.interrupts:
+            return
         # Normally, the tick counter is decremented by 1 for every message send.
         # Since we don't know how many messages are called during this trace, we
         # just decrement by 100th of the trace length (num of bytecodes).
@@ -143,6 +158,8 @@
         self.quick_check_for_interrupt(s_frame, decr_by)
     
     def quick_check_for_interrupt(self, s_frame, dec=1):
+        if not self.interrupts:
+            return
         self.interrupt_check_counter -= dec
         if self.interrupt_check_counter <= 0:
             self.interrupt_check_counter = self.interrupt_counter_size
@@ -205,7 +222,7 @@
         return self.interpret_toplevel(s_frame.w_self())
     
     def padding(self, symbol=' '):
-        return symbol * (self.max_stack_depth - self.remaining_stack_depth)
+        return symbol * self.current_stack_depth
 
 class ReturnFromTopLevel(Exception):
     _attrs_ = ["object"]
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
@@ -1014,7 +1014,7 @@
 
 class StackTestInterpreter(TestInterpreter):
     def stack_frame(self, w_frame, may_interrupt=True, fresh_context=False):
-        stack_depth = self.max_stack_depth - self.remaining_stack_depth
+        stack_depth = self.current_stack_depth
         for i in range(stack_depth + 1):
             assert sys._getframe(5 + i * 7).f_code.co_name == 'loop_bytecodes'
         assert sys._getframe(6 + stack_depth * 7).f_code.co_name == 'loop'
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -6,7 +6,7 @@
 from rpython.rlib import jit, rpath
 
 from spyvm import model, interpreter, squeakimage, objspace, wrapper,\
-    error, shadow, storage_statistics
+    error, shadow, storage_statistics, constants
 from spyvm.tool.analyseimage import create_image
 from spyvm.interpreter_proxy import VirtualMachine
 
@@ -128,13 +128,14 @@
           -r|--run [code string]
           -b|--benchmark [code string]
           -p|--poll_events
+          -ni|--no-interrupts
+          -d|--max-stack-depth [number, default %d, <= 0 disables stack protection]
           --strategy-log
           --strategy-stats
-		  --strategy-stats-dot
+          --strategy-stats-dot
           --strategy-stats-details
           [image path, default: Squeak.image]
-    """ % argv[0]
-
+    """ % (argv[0], constants.MAX_LOOP_DEPTH)
 
 def _arg_missing(argv, idx, arg):
     if len(argv) == idx + 1:
@@ -152,6 +153,8 @@
     stringarg = ""
     code = None
     as_benchmark = False
+    max_stack_depth = constants.MAX_LOOP_DEPTH
+    interrupts = True
     
     while idx < len(argv):
         arg = argv[idx]
@@ -189,6 +192,12 @@
             code = argv[idx + 1]
             as_benchmark = True
             idx += 1
+        elif arg in ["-ni", "--no-interrupts"]:
+            interrupts = False
+        elif arg in ["-d", "--max-stack-depth"]:
+            _arg_missing(argv, idx, arg)
+            max_stack_depth = int(argv[idx + 1])
+            idx += 1
         elif arg == "--strategy-log":
             storage_statistics.activate_statistics(log=True)
         elif arg == "--strategy-stats":
@@ -221,7 +230,9 @@
     space = prebuilt_space
     image_reader = squeakimage.reader_for_image(space, squeakimage.Stream(data=imagedata))
     image = create_image(space, image_reader)
-    interp = interpreter.Interpreter(space, image, image_name=path, trace=trace, evented=evented)
+    interp = interpreter.Interpreter(space, image, image_name=path,
+                trace=trace, evented=evented,
+                interrupts=interrupts, max_stack_depth=max_stack_depth)
     space.runtime_setup(argv[0])
     result = 0
     if benchmark is not None:


More information about the pypy-commit mailing list