[pypy-svn] r70595 - in pypy/trunk/pypy: interpreter module/pypyjit/test

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Jan 14 19:44:49 CET 2010


Author: cfbolz
Date: Thu Jan 14 19:44:48 2010
New Revision: 70595

Modified:
   pypy/trunk/pypy/interpreter/argument.py
   pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
Log:
Don't JIT argument parsing when the callsite has a * or ** arg, because this can
produce arbitrarily many paths. Will make the test more precise tomorrow.


Modified: pypy/trunk/pypy/interpreter/argument.py
==============================================================================
--- pypy/trunk/pypy/interpreter/argument.py	(original)
+++ pypy/trunk/pypy/interpreter/argument.py	Thu Jan 14 19:44:48 2010
@@ -4,7 +4,7 @@
 
 from pypy.interpreter.error import OperationError
 from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib.jit import purefunction, unroll_safe
+from pypy.rlib import jit
 
 
 class Signature(object):
@@ -17,7 +17,7 @@
         self.varargname = varargname
         self.kwargname = kwargname
 
-    @purefunction
+    @jit.purefunction
     def find_argname(self, name):
         try:
             return self.argnames.index(name)
@@ -101,6 +101,11 @@
         make_sure_not_resized(self.arguments_w)
         if w_stararg is not None or w_starstararg is not None:
             self._combine_wrapped(w_stararg, w_starstararg)
+            # if we have a call where * or ** args are used at the callsite
+            # we shouldn't let the JIT see the argument matching
+            self._dont_jit = True
+        else:
+            self._dont_jit = False
         
     def __repr__(self):
         """ NOT_RPYTHON """
@@ -188,13 +193,28 @@
         
     ###  Parsing for function calls  ###
 
-    @unroll_safe # XXX not true always, but for now
     def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=[],
                          blindargs=0):
         """Parse args and kwargs according to the signature of a code object,
         or raise an ArgErr in case of failure.
         Return the number of arguments filled in.
         """
+        if jit.we_are_jitted() and self._dont_jit:
+            return self._match_signature_jit_opaque(w_firstarg, scope_w,
+                                                    signature, defaults_w,
+                                                    blindargs)
+        return self._really_match_signature(w_firstarg, scope_w, signature,
+                                            defaults_w, blindargs)
+
+    @jit.dont_look_inside
+    def _match_signature_jit_opaque(self, w_firstarg, scope_w, signature,
+                                    defaults_w, blindargs):
+        return self._really_match_signature(w_firstarg, scope_w, signature,
+                                            defaults_w, blindargs)
+
+    @jit.unroll_safe
+    def _really_match_signature(self, w_firstarg, scope_w, signature, defaults_w=[],
+                                blindargs=0):
         #
         #   args_w = list of the normal actual parameters, wrapped
         #   kwds_w = real dictionary {'keyword': wrapped parameter}

Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	Thu Jan 14 19:44:48 2010
@@ -89,8 +89,12 @@
         print >> f, source
         # some support code...
         print >> f, py.code.Source("""
-            import sys, pypyjit
-            pypyjit.set_param(threshold=3)
+            import sys
+            try: # make the file runnable by CPython
+                import pypyjit
+                pypyjit.set_param(threshold=3)
+            except ImportError:
+                pass
 
             def check(args, expected):
                 print >> sys.stderr, 'trying:', args
@@ -309,6 +313,28 @@
         assert len(ops[0].get_opnames("guard")) <= 14
         assert len(ops[1].get_opnames("guard")) <= 3
 
+    def test_kwargs(self):
+        self.run_source('''
+            d = {}
+
+            def g(**args):
+                return len(args)
+
+            def main(x):
+                s = 0
+                d = {}
+                for i in range(x):
+                    s += g(**d)
+                    d[str(i)] = i
+                    if i % 100 == 99:
+                        d = {}
+                return s
+        ''', 100000, ([100], 4950),
+                    ([1000], 49500),
+                    ([10000], 495000),
+                    ([100000], 4950000))
+        assert len(self.loops) < 10
+
     def test_virtual_instance(self):
         self.run_source('''
             class A(object):



More information about the Pypy-commit mailing list