[pypy-commit] lang-smalltalk default: added two tests for block copy primitive and activation of a BlockClosure with value
lwassermann
noreply at buildbot.pypy.org
Fri Feb 22 10:32:04 CET 2013
Author: Lars Wassermann <lars.wassermann at gmail.com>
Branch:
Changeset: r80:816b5ce0926c
Date: 2013-02-21 19:46 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/816b5ce0926c/
Log: added two tests for block copy primitive and activation of a
BlockClosure with value implemented the test
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -265,12 +265,13 @@
def newClosure(self, outerContext, pc, numArgs, copiedValues):
BlockClosureShadow = self.w_BlockClosure.as_class_get_shadow(self)
- w_closure = BlockClosureShadow.new(len(copiedValues))
+ numCopied = 0 if copiedValues is self.w_nil else len(copiedValues)
+ w_closure = BlockClosureShadow.new(numCopied)
closure = wrapper.BlockClosureWrapper(self, w_closure)
closure.store_outerContext(outerContext)
closure.store_startpc(pc)
closure.store_numArgs(numArgs)
- for i0 in range(len(copiedValues)):
+ for i0 in range(numCopied):
closure.atput0(i0, copiedValues[i0])
return w_closure, closure
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -928,61 +928,64 @@
frame = interp.s_active_context()
w_context, s_context = interp.space.newClosure(outerContext, frame.pc(),
numArgs, copiedValues)
- frame.push(w_context)
+ return w_context
-def activateClosure(interp, w_block_closure, args_w, mayContextSwitch=True):
- raise PrimitiveFailedError
- if not w_block_closure.getclass(interp.space).is_same_object(
- interp.space.w_BlockClosure):
+def activateClosure(interp, w_block, args_w, mayContextSwitch=True):
+ space = interp.space
+ if not w_block.getclass(space).is_same_object(
+ space.w_BlockClosure):
raise PrimitiveFailedError()
- if not w_block_closure.numArgs == len(args_w):
+ block = wrapper.BlockClosureWrapper(space, w_block)
+ if not block.numArgs() == len(args_w):
raise PrimitiveFailedError()
- if not w_block_closure.outerContext.getclass(interp.space).issubclass(
- interp.space.w_ContextPart):
+ outer_ctxt_class = block.outerContext().getclass(space)
+ if not (outer_ctxt_class is space.w_MethodContext
+ or outer_ctxt_class is space.w_BlockContext
+ or outer_ctxt_class is space.w_BlockClosure):
raise PrimitiveFailedError()
- w_closureMethod = w_block_closure.w_method()
+
+ # additionally to the smalltalk implementation, this also pushes
+ # args and copiedValues
+ w_new_frame = block.asContextWithSender(
+ interp.w_active_context(), args_w)
+ w_closureMethod = w_new_frame.get_shadow(space).w_method()
+
assert isinstance(w_closureMethod, model.W_CompiledMethod)
- assert w_block_closure is not w_block_closure.outerContext
- numCopied = w_block_closure.size()
+ assert w_block is not block.outerContext()
- s_block_closure = w_block_closure.as_blockclosure_get_shadow(interp.space)
- s_block_closure.push_all(args_w)
+ interp.store_w_active_context(w_new_frame)
- s_block_closure.store_pc(s_block_closure.initialip())
- frame = interp.s_active_context()
- s_block_closure.store_w_sender(frame)
-
- at expose_primitive(CLOSURE_VALUE, unwrap_spec=[object])
+ at expose_primitive(CLOSURE_VALUE, unwrap_spec=[object], no_result=True)
def func(interp, w_block_closure):
activateClosure(interp, w_block_closure, [])
- at expose_primitive(CLOSURE_VALUE_, unwrap_spec=[object, object])
+ at expose_primitive(CLOSURE_VALUE_, unwrap_spec=[object, object], no_result=True)
def func(interp, w_block_closure, w_a0):
activateClosure(interp, w_block_closure, [w_a0])
- at expose_primitive(CLOSURE_VALUE_VALUE, unwrap_spec=[object, object, object])
+ at expose_primitive(CLOSURE_VALUE_VALUE, unwrap_spec=[object, object, object], no_result=True)
def func(interp, w_block_closure, w_a0, w_a1):
activateClosure(interp, w_block_closure, [w_a0, w_a1])
- at expose_primitive(CLOSURE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object])
+ at expose_primitive(CLOSURE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object], no_result=True)
def func(interp, w_block_closure, w_a0, w_a1, w_a2):
activateClosure(interp, w_block_closure, [w_a0, w_a1, w_a2])
- at expose_primitive(CLOSURE_VALUE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object, object])
+ at expose_primitive(CLOSURE_VALUE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object, object], no_result=True)
def func(interp, w_block_closure, w_a0, w_a1, w_a2, w_a3):
activateClosure(interp, w_block_closure, [w_a0, w_a1, w_a2, w_a3])
- at expose_primitive(CLOSURE_VALUE_WITH_ARGS, unwrap_spec=[object, list])
+ at expose_primitive(CLOSURE_VALUE_WITH_ARGS, unwrap_spec=[object, list], no_result=True)
def func(interp, w_block_closure, args_w):
activateClosure(interp, w_block_closure, args_w)
- at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH, unwrap_spec=[object])
+ at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH, unwrap_spec=[object], no_result=True)
def func(interp, w_block_closure):
activateClosure(interp, w_block_closure, [], mayContextSwitch=False)
- at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH_, unwrap_spec=[object, object])
+ at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH_, unwrap_spec=[object, object], no_result=True)
def func(interp, w_block_closure, w_a0):
activateClosure(interp, w_block_closure, [w_a0], mayContextSwitch=False)
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -640,7 +640,7 @@
@staticmethod
@jit.unroll_safe
def make_context(space, w_method, w_receiver,
- arguments, w_sender=None):
+ arguments, w_sender=None, closure=None, pc=0):
# From blue book: normal mc have place for 12 temps+maxstack
# mc for methods with islarge flag turned on 32
size = 12 + w_method.islarge * 20 + w_method.argsize
@@ -658,10 +658,15 @@
if w_sender:
s_result.store_w_sender(w_sender)
s_result.store_w_receiver(w_receiver)
- s_result.store_pc(0)
+ s_result.store_pc(pc)
s_result.init_stack_and_temps()
- for i in range(len(arguments)):
- s_result.settemp(i, arguments[i])
+
+ argc = len(arguments)
+ for i0 in range(argc):
+ s_result.settemp(i0, arguments[i0])
+ if closure is not None:
+ for i0 in range(closure.size()):
+ s_result.settemp(i0+argc, closure.at0(i0))
return w_result
def fetch(self, n0):
@@ -699,7 +704,11 @@
ContextPartShadow.attach_shadow(self)
def tempsize(self):
- return self.method().tempsize
+ if self.w_closure_or_nil == self.space.w_nil:
+ return self.method().tempsize
+ else:
+ return wrapper.BlockClosureWrapper(self.space,
+ self.w_closure_or_nil).tempsize()
def w_method(self):
return self._w_method
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
@@ -67,7 +67,7 @@
return lit
return [fakeliteral(lit) for lit in literals]
-def new_interpreter(bytes, receiver=space.w_nil):
+def new_interpreter(bytes, receiver=space.w_nil, space=space):
assert isinstance(bytes, str)
w_method = model.W_CompiledMethod(len(bytes))
w_method.islarge = 1
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
@@ -443,6 +443,31 @@
assert space.unwrap_char(w_c) == os.path.sep
+def test_primitive_closure_copyClosure():
+ from test_interpreter import new_interpreter
+ interp = new_interpreter("<never called, but used for method generation>")
+ w_block = prim(200, map(wrap, ["anActiveContext", 2, [wrap(1), wrap(2)]]),
+ interp.w_active_context())
+ assert w_block is not space.w_nil
+ w_w_block = wrapper.BlockClosureWrapper(space, w_block)
+ assert w_w_block.startpc() is 0
+ assert w_w_block.at0(0) == wrap(1)
+ assert w_w_block.at0(1) == wrap(2)
+ assert w_w_block.numArgs() is 2
+
+def test_primitive_closure_value():
+ from test_interpreter import new_interpreter
+ interp = new_interpreter("<never called, but used for method generation>",
+ space=space)
+ s_initial_context = interp.s_active_context()
+
+ closure, _ = space.newClosure(interp.w_active_context(), 4, 0, space.w_nil)
+ s_initial_context.push(closure)
+
+ prim_table[201](interp, 0)
+ assert interp.s_active_context().w_closure_or_nil is closure
+ assert interp.s_active_context().s_sender() is s_initial_context
+ assert interp.s_active_context().w_receiver() is space.w_nil
# Note:
# primitives.NEXT is unimplemented as it is a performance optimization
diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py
--- a/spyvm/wrapper.py
+++ b/spyvm/wrapper.py
@@ -215,9 +215,29 @@
class BlockClosureWrapper(VarsizedWrapper):
- outerContext, store_outerContext = make_getter_setter(0)
- startpc, store_startpc = make_int_getter_setter(1)
- numArgs, store_numArgs = make_int_getter_setter(2)
+ outerContext, store_outerContext = make_getter_setter(constants.BLKCLSR_OUTER_CONTEXT)
+ startpc, store_startpc = make_int_getter_setter(constants.BLKCLSR_STARTPC)
+ numArgs, store_numArgs = make_int_getter_setter(constants.BLKCLSR_NUMARGS)
+
+ def asContextWithSender(self, w_aContext, arguments):
+ from spyvm import shadow
+ s_outerContext = self.outerContext().get_shadow(self.space)
+ w_method = s_outerContext.w_method()
+ w_receiver = s_outerContext.w_receiver()
+ w_new_frame = shadow.MethodContextShadow.make_context(self.space , w_method, w_receiver,
+ arguments, w_sender=w_aContext, pc=self.startpc(), closure=self)
+ return w_new_frame
+
+ def tempsize(self):
+ # We ignore the number of temps a block has, because the first
+ # bytecodes of the block will initialize them for us. We will only
+ # use this information for decinding where the stack pointer should be
+ # initialy.
+ # For a finding the correct number, see BlockClosure>#numTemps in an Image.
+ return self.size() + self.numArgs()
+
+ def size(self):
+ return self._w_self.size() - constants.BLKCLSR_SIZE
# XXX Wrappers below are not used yet.
class OffsetWrapper(Wrapper):
More information about the pypy-commit
mailing list