[pypy-commit] lang-smalltalk interpreter-flags: Added interrupts-flag to interpreter and entry-point to disable user interrupts.
anton_gulenko
noreply at buildbot.pypy.org
Mon Jul 28 10:11:27 CEST 2014
Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: interpreter-flags
Changeset: r990:187ad8278435
Date: 2014-05-13 12:00 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/187ad8278435/
Log: Added interrupts-flag to interpreter and entry-point to disable user
interrupts. Added flag to entry-point to configure (or disable) the
max stack depth before StackOverflow protection kicks in. Fixed
indentation.
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,7 +66,7 @@
# just a trampoline for the actual loop implemented in loop_bytecodes
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:
@@ -85,7 +86,7 @@
except ProcessSwitch, p:
if self.trace:
print "====== Switched process from: %s" % s_new_context.short_str()
- print "====== to: %s " % p.s_new_context.short_str()
+ print "====== to: %s " % p.s_new_context.short_str()
s_new_context = p.s_new_context
def loop_bytecodes(self, s_context, may_context_switch=True):
@@ -116,33 +117,36 @@
else:
s_context.push(nlr.value)
- # This is just a wrapper around loop_bytecodes that handles the remaining_stack_depth mechanism
+ # 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):
- 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)
finally:
- self.remaining_stack_depth += 1
-
- def step(self, context):
- bytecode = context.fetch_next_bytecode()
- for entry in UNROLLING_BYTECODE_RANGES:
- if len(entry) == 2:
- bc, methname = entry
- if bytecode == bc:
- return getattr(context, methname)(self, bytecode)
- else:
- start, stop, methname = entry
- if start <= bytecode <= stop:
- return getattr(context, methname)(self, bytecode)
- assert 0, "unreachable"
-
+ self.current_stack_depth -= 1
+
+ def step(self, context):
+ bytecode = context.fetch_next_bytecode()
+ for entry in UNROLLING_BYTECODE_RANGES:
+ if len(entry) == 2:
+ bc, methname = entry
+ if bytecode == bc:
+ return getattr(context, methname)(self, bytecode)
+ else:
+ start, stop, methname = entry
+ if start <= bytecode <= stop:
+ return getattr(context, methname)(self, bytecode)
+ assert 0, "unreachable"
+
# ============== 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).
@@ -152,6 +156,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
@@ -214,7 +220,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
@@ -1017,7 +1017,7 @@
class StackTestInterpreter(TestInterpreter):
def stack_frame(self, w_frame, may_interrupt=True):
- 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(4 + i * 6).f_code.co_name == 'loop_bytecodes'
assert sys._getframe(5 + stack_depth * 6).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