Author: Lars Wassermann <[email protected]>
Branch:
Changeset: r240:8301476cf55c
Date: 2013-03-26 21:30 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/8301476cf55c/
Log: merge with tip and... (because merges can not be partially committed
and I forgot to commit directly) added tracing parameter and code to
interpreter fixed tracing for compiling fixed problems with stack
management in bitblt primitive and perform_with_args by adding
another parameter to expose_primitive added capabilities to shift
within 32bit range fixed the according tests
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -33,7 +33,7 @@
get_printable_location=get_printable_location
)
- def __init__(self, space, image=None, image_name="",
+ def __init__(self, space, image=None, image_name="", trace=False,
max_stack_depth=constants.MAX_LOOP_DEPTH):
self.space = space
self.image = image
@@ -44,7 +44,7 @@
self.next_wakeup_tick = 0
self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE
#
######################################################################
- # self.trace = True
+ self.trace = trace
def interpret_with_w_frame(self, w_frame):
try:
@@ -80,9 +80,9 @@
def c_loop(self, s_context):
#
######################################################################
- # if self.trace:
- # padding = ' ' * (self.max_stack_depth -
self.remaining_stack_depth)
- # print padding + s_context.short_str()
+ if self.trace:
+ padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth)
+ print padding + s_context.short_str()
old_pc = 0
if not jit.we_are_jitted():
self.quick_check_for_interrupt(s_context)
@@ -343,27 +343,31 @@
print "%sActually calling primitive %d" %
(interp._last_indent, code,)
func = primitives.prim_holder.prim_table[code]
#
##################################################################
- # if interp.trace:
- # print "%s calling primitive %d \t(%s)" % (' ' *
(interp.max_stack_depth - interp.remaining_stack_depth),
- # code, func.func_name)
+ if interp.trace:
+ print "%s calling primitive %d \t(in #%s)" % (
+ ' ' * (interp.max_stack_depth -
interp.remaining_stack_depth),
+ code, self.w_method()._likely_methodname)
try:
# note: argcount does not include rcvr
return func(interp, self, argcount)
except primitives.PrimitiveFailedError:
#
##############################################################
# if interp.trace and func.func_name !=
'raise_failing_default' and code != 83:
- # import pdb; pdb.set_trace()
+ # # import pdb; pdb.set_trace()
# try:
# func(interp, self, argcount) # will fail again
# except primitives.PrimitiveFailedError:
# pass
+ if interp.trace:
+ print "%s primitive FAILED" % (
+ ' ' * (interp.max_stack_depth -
interp.remaining_stack_depth),)
if interp.should_trace(True):
print "PRIMITIVE FAILED: %d %s" % (s_method.primitive,
w_selector.as_string(),)
pass # ignore this error and fall back to the Smalltalk version
arguments = self.pop_and_return_n(argcount)
s_frame = s_method.create_frame(self.space, receiver, arguments, self)
- self.pop()
+ self.pop() # receiver
return interp.stack_frame(s_frame)
def _doesNotUnderstand(self, w_selector, argcount, interp, receiver):
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -757,19 +757,23 @@
return retval + "---------------------\n"
def get_identifier_string(self):
- try:
- w_class = self.literals[-1]
- if isinstance(w_class, W_PointersObject):
- if w_class._shadow is None:
- classname = w_class._fetch(1)._shadow.getname()
- else:
- classname = w_class._shadow.getname()
- else:
- classname = "<unknown>"
- except (IndexError, AttributeError):
- classname = "<unknown>"
+ from spyvm import shadow
+ classname = '<unknown>'
+ if len(self.literals) > 0:
+ w_candidate = self.literals[-1]
+ if isinstance(w_candidate, W_PointersObject):
+ c_shadow = w_candidate._shadow
+ if c_shadow is None:
+ w_class = w_candidate._fetch(1)
+ if isinstance(w_class, W_PointersObject):
+ d_shadow = w_class._shadow
+ if isinstance(d_shadow, shadow.ClassShadow):
+ classname = d_shadow.getname()
+ elif isinstance(shadow, shadow.ClassShadow):
+ classname = c_shadow.getname()
return "%s>>#%s" % (classname, self._likely_methodname)
+
def invariant(self):
return (W_Object.invariant(self) and
hasattr(self, 'literals') and
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -52,7 +52,7 @@
char = object()
pos_32bit_int = object()
-def expose_primitive(code, unwrap_spec=None, no_result=False,
result_is_new_frame=False):
+def expose_primitive(code, unwrap_spec=None, no_result=False,
result_is_new_frame=False, clean_stack=True):
# some serious magic, don't look
from rpython.rlib.unroll import unrolling_iterable
# heuristics to give it a nice name
@@ -121,13 +121,17 @@
s_new_frame = func(interp, s_frame, *args)
# After calling primitive, reload context-shadow in case it
# needs to be updated
- s_frame.pop_n(len_unwrap_spec) # only if no exception
occurs!
+ if clean_stack:
+ # happens only if no exception occurs!
+ s_frame.pop_n(len_unwrap_spec)
return interp.stack_frame(s_new_frame)
else:
w_result = func(interp, s_frame, *args)
# After calling primitive, reload context-shadow in case it
# needs to be updated
- s_frame.pop_n(len_unwrap_spec) # only if no exception
occurs!
+ if clean_stack:
+ # happens only if no exception occurs!
+ s_frame.pop_n(len_unwrap_spec)
if not no_result:
assert w_result is not None
assert isinstance(w_result, model.W_Object)
@@ -223,12 +227,20 @@
# (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types)
# left shift, must fail if we lose bits beyond 32
+ from rpython.rlib.rarithmetic import intmask, r_uint, ovfcheck, int_between
if argument > 0:
- try:
- shifted = rarithmetic.ovfcheck(receiver << argument)
- except OverflowError:
- raise PrimitiveFailedError()
- return interp.space.wrap_int(shifted)
+ # argument > 0, therefore the highest bit of upperbound is not set,
+ # i.e. upperbound is positive
+ upperbound = intmask(r_uint(-1) >> argument)
+ if 0 <= receiver <= upperbound:
+ shifted = intmask(receiver << argument)
+ return interp.space.wrap_positive_32bit_int(shifted)
+ else:
+ try:
+ shifted = ovfcheck(receiver << argument)
+ except OverflowError:
+ raise PrimitiveFailedError()
+ return interp.space.wrap_int(shifted)
# right shift, ok to lose bits
else:
@@ -556,13 +568,12 @@
def func(interp, s_frame, w_rcvr):
raise PrimitiveNotYetWrittenError()
-@expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object])
+@expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object], clean_stack=False)
def func(interp, s_frame, w_rcvr):
if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15:
raise PrimitiveFailedError
space = interp.space
- s_frame.push(w_rcvr)
s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp)
w_dest_form = w_rcvr.fetch(space, 0)
@@ -571,6 +582,7 @@
assert isinstance(w_bitmap, model.W_DisplayBitmap)
w_bitmap.flush_to_screen()
+ # in case we return normally, we have to restore the removed w_rcvr
return w_rcvr
@expose_primitive(BE_CURSOR, unwrap_spec=[object])
@@ -1100,21 +1112,14 @@
@expose_primitive(PERFORM_WITH_ARGS,
unwrap_spec=[object, object, list],
- no_result=True)
+ no_result=True, clean_stack=False)
def func(interp, s_frame, w_rcvr, w_selector, args_w):
- stackvalues = s_frame.pop_and_return_n(3)
argcount = len(args_w)
# pushing the receiver and args to be popped by _sendSelector
s_frame.push(w_rcvr)
s_frame.push_all(args_w)
s_frame._sendSelector(w_selector, argcount, interp,
w_rcvr, w_rcvr.shadow_of_my_class(interp.space))
- # If we return in a regular way, we need to rebuild the former
- # stack-contents to be collected by the primitive wrapper, i.a. if
- # w_selector points to a primitive method. But if we have an exception, the
- # wrapper will not clean. Therefore we should not put this into a finally.
- s_frame.push_all(stackvalues)
-
@expose_primitive(SIGNAL, unwrap_spec=[object])
def func(interp, s_frame, w_rcvr):
diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py
--- a/spyvm/test/test_primitives.py
+++ b/spyvm/test/test_primitives.py
@@ -167,13 +167,16 @@
assert prim(primitives.BIT_SHIFT, [-4, 27]).value == -536870912
def test_small_int_bit_shift_fail():
+ from rpython.rlib.rarithmetic import intmask
prim_fails(primitives.BIT_SHIFT, [4, 32])
prim_fails(primitives.BIT_SHIFT, [4, 31])
prim_fails(primitives.BIT_SHIFT, [4, 30])
- prim_fails(primitives.BIT_SHIFT, [4, 29])
- w_result = prim_fails(primitives.BIT_SHIFT, [4, 28])
- # assert isinstance(w_result, model.W_LargePositiveInteger1Word)
- # assert w_result.value == 4 << 28
+ w_result = prim(primitives.BIT_SHIFT, [4, 29])
+ assert isinstance(w_result, model.W_LargePositiveInteger1Word)
+ assert w_result.value == intmask(4 << 29)
+ w_result = prim(primitives.BIT_SHIFT, [4, 28])
+ assert isinstance(w_result, model.W_LargePositiveInteger1Word)
+ assert w_result.value == 4 << 28
def test_smallint_as_float():
assert prim(primitives.SMALLINT_AS_FLOAT, [12]).value == 12.0
@@ -709,8 +712,7 @@
prim_table[primitives.BITBLT_COPY_BITS](interp,
w_frame.as_context_get_shadow(space), argument_count-1)
finally:
monkeypatch.undo()
- assert w_frame._shadow.pop() is mock_bitblt # the new receiver
- assert w_frame._shadow.pop() is mock_bitblt # previous state is still there
+ assert w_frame._shadow.pop() is mock_bitblt # the receiver
# Note:
# primitives.NEXT is unimplemented as it is a performance optimization
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -57,6 +57,7 @@
path = None
number = 0
benchmark = None
+ trace = False
while idx < len(argv):
arg = argv[idx]
@@ -76,6 +77,8 @@
_arg_missing(argv, idx, arg)
benchmark = argv[idx + 1]
idx += 1
+ elif arg in ["-t", "--trace"]:
+ trace = True
elif path is None:
path = argv[idx]
else:
@@ -87,7 +90,7 @@
path = "Squeak.image"
try:
- f = open_file_as_stream(path)
+ f = open_file_as_stream(path, buffering=0)
except OSError as e:
os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path))
return 1
@@ -98,7 +101,7 @@
image_reader = squeakimage.reader_for_image(space,
squeakimage.Stream(data=imagedata))
image = create_image(space, image_reader)
- interp = interpreter.Interpreter(space, image,
image_name=os.path.abspath(path))
+ interp = interpreter.Interpreter(space, image, image_name=path,
trace=trace)
if benchmark is not None:
return _run_benchmark(interp, number, benchmark)
else:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit