[pypy-commit] lang-smalltalk storage: use StackOverflow protection from rlib

timfel noreply at buildbot.pypy.org
Thu Jul 10 15:29:29 CEST 2014


Author: Tim Felgentreff <timfelgentreff at gmail.com>
Branch: storage
Changeset: r888:afd77668220d
Date: 2014-07-10 12:00 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/afd77668220d/

Log:	use StackOverflow protection from rlib

diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -190,6 +190,5 @@
 # Interpreter constants
 #
 
-MAX_LOOP_DEPTH = 100
 INTERRUPT_COUNTER_SIZE = 10000
 CompileTime = time.time()
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -4,7 +4,7 @@
 from spyvm import model, constants, primitives, conftest, wrapper
 from spyvm.tool.bitmanipulation import splitter
 
-from rpython.rlib import jit
+from rpython.rlib import jit, rstackovf
 from rpython.rlib import objectmodel, unroll
 
 class MissingBytecode(Exception):
@@ -24,7 +24,7 @@
 
 class Interpreter(object):
     _immutable_fields_ = ["space", "image", "image_name",
-                          "max_stack_depth", "interrupt_counter_size",
+                          "interrupt_counter_size",
                           "startup_time", "evented", "interrupts"]
 
     jit_driver = jit.JitDriver(
@@ -35,8 +35,7 @@
     )
 
     def __init__(self, space, image=None, image_name="",
-                trace=False, evented=True, interrupts=True,
-                max_stack_depth=constants.MAX_LOOP_DEPTH):
+                trace=False, evented=True, interrupts=True):
         import time
 
         # === Initialize immutable variables
@@ -47,7 +46,6 @@
             self.startup_time = image.startup_time
         else:
             self.startup_time = constants.CompileTime
-        self.max_stack_depth = max_stack_depth
         self.evented = evented
         self.interrupts = interrupts
         try:
@@ -57,7 +55,6 @@
 
         # === Initialize mutable variables
         self.interrupt_check_counter = self.interrupt_counter_size
-        self.current_stack_depth = 0
         self.next_wakeup_tick = 0
         self.trace = trace
         self.trace_proxy = False
@@ -66,7 +63,6 @@
         # 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.current_stack_depth == 0
             s_sender = s_new_context.s_sender()
             try:
                 self.loop_bytecodes(s_new_context)
@@ -122,16 +118,11 @@
         try:
             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
+        except rstackovf.StackOverflow:
+            rstackovf.check_stack_overflow()
+            raise StackOverflow(s_frame)
 
     def step(self, context):
         bytecode = context.fetch_next_bytecode()
@@ -205,7 +196,7 @@
         s_frame = self.create_toplevel_context(w_receiver, selector, w_selector, w_arguments)
         self.interrupt_check_counter = self.interrupt_counter_size
         return self.interpret_toplevel(s_frame.w_self())
-    
+
     def create_toplevel_context(self, w_receiver, selector="", w_selector=None, w_arguments=[]):
         if w_selector is None:
             assert selector, "Need either string or W_Object selector"
@@ -213,7 +204,7 @@
                 w_selector = self.image.w_asSymbol
             else:
                 w_selector = self.perform(self.space.wrap_string(selector), "asSymbol")
-        
+
         w_method = model.W_CompiledMethod(self.space, header=512)
         w_method.literalatput0(self.space, 1, w_selector)
         assert len(w_arguments) <= 7
@@ -225,7 +216,7 @@
         return s_frame
 
     def padding(self, symbol=' '):
-        return symbol * self.current_stack_depth
+        return symbol
 
 class ReturnFromTopLevel(Exception):
     _attrs_ = ["object"]
@@ -964,11 +955,9 @@
 # in order to enable tracing/jumping for message sends etc.
 def debugging():
     def stepping_debugger_init(original):
-        def meth(self, space, image=None, image_name="", trace=False,
-                max_stack_depth=constants.MAX_LOOP_DEPTH):
+        def meth(self, space, image=None, image_name="", trace=False):
             return_value = original(self, space, image=image,
-                                    image_name=image_name, trace=trace,
-                                    max_stack_depth=max_stack_depth)
+                                    image_name=image_name, trace=trace)
             # ##############################################################
 
             self.message_stepping = False
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -14,13 +14,13 @@
     print """
     Usage: %s <path> [-r|-m] [-naHu] [-jpis] [-tlLE]
             <path> - image path (default: Squeak.image)
-          
+
           Execution mode:
             (no flags)             - Image will be normally opened.
             -r|--run <code>        - Code will be compiled and executed, result printed.
             -m|--method <selector> - Selector will be sent to a SmallInteger, result printed.
             -h|--help              - Output this and exit.
-            
+
           Execution parameters:
             -n|--num <int> - Only with -m or -r, SmallInteger to be used as receiver (default: nil).
             -a|--arg <arg> - Only with -m, will be used as single String argument.
@@ -30,28 +30,25 @@
                              in the image and execute the context directly. The image window will
                              probably not open. Good for benchmarking.
             -u             - Only with -m or -r, try to stop UI-process at startup. Can help benchmarking.
-            
+
           Other parameters:
             -j|--jit <jitargs> - jitargs will be passed to the jit configuration.
             -p|--poll          - Actively poll for events. Try this if the image is not responding well.
             -i|--no-interrupts - Disable timer interrupt. Disables non-cooperative scheduling.
-            -s <num>           - After num stack frames, the entire stack will be dumped to the heap.
-                                 This breaks performance, but protects agains stack overflow.
-                                 num <= 0 disables stack protection (default: %d)
-            
+
           Logging parameters:
             -t|--trace                 - Output a trace of each message, primitive, return value and process switch.
             -l|--storage-log           - Output a log of storage operations.
             -L|--storage-log-aggregate - Output an aggregated storage log at the end of execution.
             -E|--storage-log-elements  - Include classnames of elements into the storage log.
-            
-    """ % (argv[0], constants.MAX_LOOP_DEPTH)
+
+    """ % argv[0]
 
 def get_parameter(argv, idx, arg):
     if len(argv) < idx + 1:
         raise RuntimeError("Error: missing argument after %s" % arg)
     return argv[idx], idx + 1
-    
+
 prebuilt_space = objspace.ObjSpace()
 
 def entry_point(argv):
@@ -65,12 +62,11 @@
     # == Other parameters
     poll = False
     interrupts = True
-    max_stack_depth = constants.MAX_LOOP_DEPTH
     trace = False
-    
+
     path = argv[1] if len(argv) > 1 else "Squeak.image"
     idx = 2
-    
+
     while idx < len(argv):
         arg = argv[idx]
         idx += 1
@@ -96,9 +92,6 @@
             code, idx = get_parameter(argv, idx, arg)
         elif arg in ["-i", "--no-interrupts"]:
             interrupts = False
-        elif arg in ["-s"]:
-            arg, idx = get_parameter(argv, idx, arg)
-            max_stack_depth = int(arg)
         elif arg in ["-P", "--process"]:
             headless = False
         elif arg in ["-u"]:
@@ -113,10 +106,10 @@
         else:
             _usage(argv)
             return -1
-    
+
     if code and selector:
         raise RuntimeError("Cannot handle both -r and -m.")
-    
+
     path = rpath.rabspath(path)
     try:
         f = open_file_as_stream(path, mode="rb", buffering=0)
@@ -127,16 +120,16 @@
     except OSError as e:
         os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path))
         return 1
-    
+
     # Load & prepare image and environment
     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=not poll,
-                interrupts=interrupts, max_stack_depth=max_stack_depth)
+                interrupts=interrupts)
     space.runtime_setup(argv[0])
-    
+
     # Create context to be executed
     if code or selector:
         if not have_number:
@@ -155,7 +148,7 @@
             context = active_context(interp.space)
     else:
         context = active_context(interp.space)
-    
+
     w_result = execute_context(interp, context)
     print result_string(w_result)
     storage_logger.print_aggregated_log()
@@ -198,13 +191,13 @@
         return None
     w_receiver_class.as_class_get_shadow(space).s_methoddict().sync_method_cache()
     return selector
-    
+
 def create_context(interp, w_receiver, selector, stringarg):
     args = []
     if stringarg:
         args.append(interp.space.wrap_string(stringarg))
     return interp.create_toplevel_context(w_receiver, selector, w_arguments = args)
-    
+
 def create_process(interp, s_frame):
     space = interp.space
     w_active_process = wrapper.scheduler(space).active_process()
@@ -221,10 +214,10 @@
         priority = 7
     w_benchmark_proc.store(space, 1, s_frame.w_self())
     w_benchmark_proc.store(space, 2, space.wrap_int(priority))
-    
+
     # Make process eligible for scheduling
     wrapper.ProcessWrapper(space, w_benchmark_proc).put_to_sleep()
-    
+
 def active_context(space):
     w_active_process = wrapper.scheduler(space).active_process()
     active_process = wrapper.ProcessWrapper(space, w_active_process)
@@ -240,7 +233,7 @@
     except error.Exit, e:
         print "Exited: %s" % e.msg
         return None
-    
+
 # _____ Target and Main _____
 
 def target(driver, *args):


More information about the pypy-commit mailing list