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