[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