Author: Lars Wassermann <[email protected]>
Branch:
Changeset: r376:46932f9d0142
Date: 2013-05-06 14:15 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/46932f9d0142/
Log: added ensure:/ifCurtailed: checks when unwinding added tests to be
executed in the benchmarks 4.5 image because this is the only one
where there is an #ensure:-Implementation added two tests for ensure
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -75,6 +75,8 @@
s_new_context = s_sender
while s_new_context is not nlr.s_target_context:
s_sender = s_new_context.s_sender()
+ if not s_new_context.is_closure_context() and
s_new_context.s_method().primitive() == 198:
+ s_new_context.activate_unwind_context(self)
s_new_context.mark_returned()
s_new_context = s_sender
s_new_context.push(nlr.value)
@@ -105,6 +107,8 @@
self.step(s_context)
except Return, nlr:
if nlr.s_target_context is not s_context:
+ if not s_context.is_closure_context() and
s_context.s_method().primitive() == 198:
+ s_context.activate_unwind_context(self)
s_context.mark_returned()
raise nlr
else:
@@ -414,6 +418,20 @@
print '%s<- %s' % (interp.padding(), return_value.as_repr_string())
raise Return(return_value, s_return_to)
+ def activate_unwind_context(self, interp):
+ # the first temp is executed flag for both #ensure: and #ifCurtailed:
+ if self.gettemp(1) is self.space.w_nil:
+ self.settemp(1, self.space.w_true) # mark unwound
+ self.push(self.gettemp(0)) # push the first argument
+ try:
+ self.bytecodePrimValue(interp, 0)
+ except Return, nlr:
+ if self is nlr.s_target_context:
+ return
+ else:
+ self.mark_returned()
+ raise nlr
+
def returnReceiver(self, interp, current_bytecode):
return self._return(self.w_receiver(), interp,
self.s_home().s_sender())
diff --git a/spyvm/test/test_bootstrappedimage.py
b/spyvm/test/test_bootstrappedimage.py
--- a/spyvm/test/test_bootstrappedimage.py
+++ b/spyvm/test/test_bootstrappedimage.py
@@ -15,7 +15,7 @@
return each
def initialize_class(w_class):
- initialize_symbol = find_symbol_in_methoddict_of("initialize",
+ initialize_symbol = find_symbol_in_methoddict_of("initialize",
w_class.shadow_of_my_class(tools.space))
perform(w_class, initialize_symbol)
@@ -35,7 +35,7 @@
def test_retrieve_symbol():
"""asSymbol
- "This is the only place that new Symbols are created. A Symbol is created
+ "This is the only place that new Symbols are created. A Symbol is created
if and only if there is not already a Symbol with its contents in
existance."
Symbol
allInstancesDo: [ :sym |
diff --git a/spyvm/test/test_in_squeak_4_5_image.py
b/spyvm/test/test_in_squeak_4_5_image.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/test_in_squeak_4_5_image.py
@@ -0,0 +1,84 @@
+import py
+from spyvm import squeakimage, model, constants
+from spyvm import interpreter, shadow, objspace
+from spyvm.test import test_miniimage as tools
+from spyvm.test.test_miniimage import perform, w
+
+tools.setup_module(tools, filename='Squeak4.5-12568.image')
+
+def find_symbol_in_methoddict_of(string, s_class):
+ s_methoddict = s_class.s_methoddict()
+ s_methoddict.sync_cache()
+ methoddict_w = s_methoddict.methoddict
+ for each in methoddict_w.keys():
+ if each.as_string() == string:
+ return each
+
+def test_all_pointers_are_valid():
+ tools.test_all_pointers_are_valid()
+ tools.test_lookup_abs_in_integer()
+
+def create_method_shadow(bytes, literals=[], islarge=0, argsize=0, tempsize=0):
+ w_method = model.W_CompiledMethod(len(bytes))
+ w_method.bytes = bytes
+ w_method.islarge = islarge
+ w_method.argsize = argsize
+ w_method.tempsize = tempsize
+
+ w_method.setliterals(literals)
+ s_method = w_method.as_compiledmethod_get_shadow(tools.space)
+ return s_method
+
+def test_ensure():
+ space = tools.space
+ #ensure
+ # [^'b1'] ensure: [^'b2']
+ import operator
+ bytes = reduce(operator.add, map(chr, [0x8F, 0, 0, 2, 0x21, 0x7c,
+ 0x8F, 0, 0, 2, 0x22, 0x7c,
+ 0xe0, 0x87, 0x78]))
+
+ s_class = space.w_BlockClosure.as_class_get_shadow(space)
+ ensure_ = find_symbol_in_methoddict_of('ensure:', s_class)
+ assert ensure_ is not None, 'Using image without #ensure:-method.'
+
+ s_method = create_method_shadow(bytes, [ensure_, w('b1'), w('b2'),
+ w('ensure'), space.w_BlockClosure])
+
+ # create a frame for our newly crafted method with a valid sender (to
avoid raising returnFromTop to early)
+ s_initial_frame = create_method_shadow(chr(0x7c)).create_frame(space,
w(0), [])
+ w_frame = s_method.create_frame(space, w(0), [],
sender=s_initial_frame).w_self()
+
+ try:
+ tools.interp.loop(w_frame)
+ except interpreter.ReturnFromTopLevel, e:
+ assert e.object.as_string() == 'b2'
+ except interpreter.StackOverflow, e:
+ assert False
+
+def test_ensure_save_original_nlr():
+ space = tools.space
+ #ensure
+ # [^'b1'] ensure: ['b2']
+ import operator
+ bytes = reduce(operator.add, map(chr, [0x8F, 0, 0, 2, 0x21, 0x7c,
+ 0x8F, 0, 0, 2, 0x22, 0x7d,
+ 0xe0, 0x87, 0x78]))
+
+ s_class = space.w_BlockClosure.as_class_get_shadow(space)
+ ensure_ = find_symbol_in_methoddict_of('ensure:', s_class)
+ assert ensure_ is not None, 'Using image without #ensure:-method.'
+
+ s_method = create_method_shadow(bytes, [ensure_, w('b1'), w('b2'),
+ w('ensure'), space.w_BlockClosure])
+
+ # create a frame for our newly crafted method with a valid sender (to
avoid raising returnFromTop to early)
+ s_initial_frame = create_method_shadow(chr(0x7c)).create_frame(space,
w(0), [])
+ w_frame = s_method.create_frame(space, w(0), [],
sender=s_initial_frame).w_self()
+
+ try:
+ tools.interp.loop(w_frame)
+ except interpreter.ReturnFromTopLevel, e:
+ assert e.object.as_string() == 'b1'
+ except interpreter.StackOverflow, e:
+ assert False
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit