1. arp11
  2. pypy-arp11

Commits

Alex Gaynor  committed b494ff6

(alex, with review from arigo and antocuni) Improve function defaults by showing the JIT that the memory they reside in is constant, evne if function.func_defaults isn't

  • Participants
  • Parent commits 143c77a
  • Branches default

Comments (0)

Files changed (6)

File pypy/interpreter/function.py

View file
     assert not func.can_change_code
     return func.code
 
+class Defaults(object):
+    _immutable_fields_ = ["items[*]"]
+
+    def __init__(self, items):
+        self.items = items
+
+    def getitems(self):
+        return jit.hint(self, promote=True).items
+
 class Function(Wrappable):
     """A function is a code object captured with some environment:
     an object space, a dictionary of globals, default arguments,
         self.code = code       # Code instance
         self.w_func_globals = w_globals  # the globals dictionary
         self.closure   = closure    # normally, list of Cell instances or None
-        self.defs_w    = defs_w     # list of w_default's
-        make_sure_not_resized(self.defs_w)
+        self.defs = Defaults(defs_w)     # wrapper around list of w_default's
         self.w_func_dict = None # filled out below if needed
         self.w_module = None
 
                 assert isinstance(code, gateway.BuiltinCode4)
                 return code.fastcall_4(self.space, self, args_w[0],
                                        args_w[1], args_w[2], args_w[3])
-        elif (nargs|PyCode.FLATPYCALL) == fast_natural_arity:
+        elif (nargs | PyCode.FLATPYCALL) == fast_natural_arity:
             assert isinstance(code, PyCode)
             if nargs < 5:
                 new_frame = self.space.createframe(code, self.w_func_globals,
                 return code.fastcall_4(self.space, self, frame.peekvalue(3),
                                        frame.peekvalue(2), frame.peekvalue(1),
                                         frame.peekvalue(0))
-        elif (nargs|Code.FLATPYCALL) == fast_natural_arity:
+        elif (nargs | Code.FLATPYCALL) == fast_natural_arity:
             assert isinstance(code, PyCode)
             return self._flat_pycall(code, nargs, frame)
-        elif fast_natural_arity&Code.FLATPYCALL:
-            natural_arity = fast_natural_arity&0xff
-            if natural_arity > nargs >= natural_arity-len(self.defs_w):
+        elif fast_natural_arity & Code.FLATPYCALL:
+            natural_arity = fast_natural_arity & 0xff
+            if natural_arity > nargs >= natural_arity - len(self.defs.getitems()):
                 assert isinstance(code, PyCode)
                 return self._flat_pycall_defaults(code, nargs, frame,
-                                                  natural_arity-nargs)
+                                                  natural_arity - nargs)
         elif fast_natural_arity == Code.PASSTHROUGHARGS1 and nargs >= 1:
             assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
             w_obj = frame.peekvalue(nargs-1)
             w_arg = frame.peekvalue(nargs-1-i)
             new_frame.fastlocals_w[i] = w_arg
 
-        defs_w = self.defs_w
+        defs_w = self.defs.getitems()
         ndefs = len(defs_w)
-        start = ndefs-defs_to_load
+        start = ndefs - defs_to_load
         i = nargs
         for j in xrange(start, ndefs):
             new_frame.fastlocals_w[i] = defs_w[j]
         return self.w_func_dict
 
     def setdict(self, space, w_dict):
-        if not space.is_true(space.isinstance( w_dict, space.w_dict )):
-            raise OperationError( space.w_TypeError, space.wrap("setting function's dictionary to a non-dict") )
+        if not space.isinstance_w(w_dict, space.w_dict):
+            raise OperationError(space.w_TypeError,
+                space.wrap("setting function's dictionary to a non-dict")
+            )
         self.w_func_dict = w_dict
 
     def descr_function__new__(space, w_subtype, w_code, w_globals,
             w(self.code),
             w_func_globals,
             w_closure,
-            nt(self.defs_w),
+            nt(self.defs.getitems()),
             w_func_dict,
             self.w_module,
         ]
         from pypy.interpreter.pycode import PyCode
         args_w = space.unpackiterable(w_args)
         try:
-            (w_name, w_doc, w_code, w_func_globals, w_closure, w_defs_w,
+            (w_name, w_doc, w_code, w_func_globals, w_closure, w_defs,
              w_func_dict, w_module) = args_w
         except ValueError:
             # wrong args
         if space.is_w(w_func_dict, space.w_None):
             w_func_dict = None
         self.w_func_dict = w_func_dict
-        self.defs_w    = space.fixedview(w_defs_w)
+        self.defs = Defaults(space.fixedview(w_defs))
         self.w_module = w_module
 
     def fget_func_defaults(self, space):
-        values_w = self.defs_w
+        values_w = self.defs.getitems()
+        # the `None in values_w` check here is to ensure that interp-level
+        # functions with a default of NoneNotWrapped do not get their defaults
+        # exposed at applevel
         if not values_w or None in values_w:
             return space.w_None
         return space.newtuple(values_w)
 
     def fset_func_defaults(self, space, w_defaults):
         if space.is_w(w_defaults, space.w_None):
-            self.defs_w = []
+            self.defs = Defaults([])
             return
         if not space.is_true(space.isinstance(w_defaults, space.w_tuple)):
             raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object or None") )
-        self.defs_w = space.fixedview(w_defaults)
+        self.defs = Defaults(space.fixedview(w_defaults))
 
     def fdel_func_defaults(self, space):
-        self.defs_w = []
+        self.defs = Defaults([])
 
     def fget_func_doc(self, space):
         if self.w_doc is None:
     def fget___module__(self, space):
         if self.w_module is None:
             if self.w_func_globals is not None and not space.is_w(self.w_func_globals, space.w_None):
-                self.w_module = space.call_method( self.w_func_globals, "get", space.wrap("__name__") )
+                self.w_module = space.call_method(self.w_func_globals, "get", space.wrap("__name__"))
             else:
                 self.w_module = space.w_None
         return self.w_module
     def __init__(self, func):
         assert isinstance(func, Function)
         Function.__init__(self, func.space, func.code, func.w_func_globals,
-                          func.defs_w, func.closure, func.name)
+                          func.defs.getitems(), func.closure, func.name)
         self.w_doc = func.w_doc
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module

File pypy/interpreter/gateway.py

View file
 NoneNotWrapped = object()
 
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.interpreter.error import OperationError 
+from pypy.interpreter.error import OperationError
 from pypy.interpreter import eval
 from pypy.interpreter.function import Function, Method, ClassMethod
 from pypy.interpreter.function import FunctionWithFixedCode
 from pypy.rlib import rstackovf
 from pypy.rlib.objectmodel import we_are_translated
 
-# internal non-translatable parts: 
+# internal non-translatable parts:
 import py
 
 class SignatureBuilder(object):
         dispatch = self.dispatch
         for el in unwrap_spec:
             dispatch(el, *extra)
-            
+
 class UnwrapSpecEmit(UnwrapSpecRecipe):
 
     def __init__(self):
         self.n = 0
         self.miniglobals = {}
-        
+
     def succ(self):
         n = self.n
         self.n += 1
         name = obj.__name__
         self.miniglobals[name] = obj
         return name
-    
+
 #________________________________________________________________
 
 class UnwrapSpec_Check(UnwrapSpecRecipe):
             "unwrapped %s argument %s of built-in function %r should "
             "not start with 'w_'" % (name, argname, self.func))
         app_sig.append(argname)
-        
+
     def visit__ObjSpace(self, el, app_sig):
         self.orig_arg()
 
             (argname, self.func))
         assert app_sig.varargname is None,(
             "built-in function %r has conflicting rest args specs" % self.func)
-        app_sig.varargname = argname[:-2]    
+        app_sig.varargname = argname[:-2]
 
     def visit_w_args(self, el, app_sig):
         argname = self.orig_arg()
 
     def scopenext(self):
         return "scope_w[%d]" % self.succ()
-    
+
     def visit_function(self, (func, cls)):
         self.run_args.append("%s(%s)" % (self.use(func),
                                          self.scopenext()))
     def visit_self(self, typ):
         self.run_args.append("space.descr_self_interp_w(%s, %s)" %
                              (self.use(typ), self.scopenext()))
-        
+
     def visit__Wrappable(self, typ):
         self.run_args.append("space.interp_w(%s, %s)" % (self.use(typ),
                                                          self.scopenext()))
                 "unexpected: same spec, different run_args")
             return activation_factory_cls
         except KeyError:
-            parts = []          
+            parts = []
             for el in unwrap_spec:
                 if isinstance(el, tuple):
                     parts.append(''.join([getattr(subel, '__name__', subel)
             #print label
 
             d = {}
-            source = """if 1: 
+            source = """if 1:
                 def _run(self, space, scope_w):
                     return self.behavior(%s)
                 \n""" % (', '.join(self.run_args),)
         self.finger += 1
         if self.n > 4:
             raise FastFuncNotSupported
-        
+
     def nextarg(self):
         arg = "w%d" % self.succ()
         self.args.append(arg)
                     raise FastFuncNotSupported
             d = {}
             unwrap_info.miniglobals['func'] = func
-            source = """if 1: 
+            source = """if 1:
                 def fastfunc_%s_%d(%s):
                     return func(%s)
                 \n""" % (func.__name__, narg,
         # 'w_args' for rest arguments passed as wrapped tuple
         # str,int,float: unwrap argument as such type
         # (function, cls) use function to check/unwrap argument of type cls
-        
+
         # First extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
         argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
         else:
             assert descrmismatch is None, (
                 "descrmismatch without a self-type specified")
- 
+
 
         orig_sig = SignatureBuilder(func, argnames, varargname, kwargname)
         app_sig = SignatureBuilder(func)
         space = func.space
         activation = self.activation
         scope_w = args.parse_obj(w_obj, func.name, self.sig,
-                                 func.defs_w, self.minargs)
+                                 func.defs.getitems(), self.minargs)
         try:
             w_result = activation._run(space, scope_w)
         except DescrMismatch:
             if not we_are_translated():
                 raise
             raise e
-        except KeyboardInterrupt: 
+        except KeyboardInterrupt:
             raise OperationError(space.w_KeyboardInterrupt,
-                                 space.w_None) 
-        except MemoryError: 
+                                 space.w_None)
+        except MemoryError:
             raise OperationError(space.w_MemoryError, space.w_None)
         except rstackovf.StackOverflow, e:
             rstackovf.check_stack_overflow()
 class BuiltinCode0(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 0
-    
+
     def fastcall_0(self, space, w_func):
         try:
             w_result = self.fastfunc_0(space)
 class BuiltinCode1(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 1
-    
+
     def fastcall_1(self, space, w_func, w1):
         try:
             w_result = self.fastfunc_1(space, w1)
 class BuiltinCode2(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 2
-    
+
     def fastcall_2(self, space, w_func, w1, w2):
         try:
             w_result = self.fastfunc_2(space, w1, w2)
 class BuiltinCode3(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 3
-    
+
     def fastcall_3(self, space, func, w1, w2, w3):
         try:
             w_result = self.fastfunc_3(space, w1, w2, w3)
 class BuiltinCode4(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 4
-    
+
     def fastcall_4(self, space, func, w1, w2, w3, w4):
         try:
             w_result = self.fastfunc_4(space, w1, w2, w3, w4)
     NOT_RPYTHON_ATTRIBUTES = ['_staticdefs']
 
     instancecache = {}
-    
+
     def __new__(cls, f, app_name=None, unwrap_spec = None,
                 descrmismatch=None, as_classmethod=False):
 
         return fn
 
 
-# 
-# the next gateways are to be used only for 
-# temporary/initialization purposes 
-     
-class interp2app_temp(interp2app): 
+#
+# the next gateways are to be used only for
+# temporary/initialization purposes
+
+class interp2app_temp(interp2app):
     "NOT_RPYTHON"
-    def getcache(self, space): 
+    def getcache(self, space):
         return self.__dict__.setdefault(space, GatewayCache(space))
 
 
-# and now for something completely different ... 
+# and now for something completely different ...
 #
 
 class ApplevelClass:
         from pypy.interpreter.module import Module
         return Module(space, space.wrap(name), self.getwdict(space))
 
-    def wget(self, space, name): 
-        w_globals = self.getwdict(space) 
+    def wget(self, space, name):
+        w_globals = self.getwdict(space)
         return space.getitem(w_globals, space.wrap(name))
 
     def interphook(self, name):
         "NOT_RPYTHON"
         def appcaller(space, *args_w):
-            if not isinstance(space, ObjSpace): 
+            if not isinstance(space, ObjSpace):
                 raise TypeError("first argument must be a space instance.")
             # redirect if the space handles this specially
             # XXX can this be factored a bit less flow space dependently?
                                                       args.arguments_w)
             return space.call_args(w_func, args)
         def get_function(space):
-            w_func = self.wget(space, name) 
+            w_func = self.wget(space, name)
             return space.unwrap(w_func)
         appcaller = func_with_new_name(appcaller, name)
         appcaller.get_function = get_function
     myfunc = appdef('''myfunc(x, y):
                            return x+y
                     ''')
-    """ 
-    if not isinstance(source, str): 
+    """
+    if not isinstance(source, str):
         source = py.std.inspect.getsource(source).lstrip()
         while source.startswith('@py.test.mark.'):
             # these decorators are known to return the same function
             # object, we may ignore them
             assert '\n' in source
             source = source[source.find('\n') + 1:].lstrip()
-        assert source.startswith("def "), "can only transform functions" 
+        assert source.startswith("def "), "can only transform functions"
         source = source[4:]
     p = source.find('(')
     assert p >= 0

File pypy/interpreter/pycode.py

View file
         self._init_flags()
         # Precompute what arguments need to be copied into cellvars
         self._args_as_cellvars = []
-        
+
         if self.co_cellvars:
             argcount = self.co_argcount
             assert argcount >= 0     # annotator hint
 
     def signature(self):
         return self._signature
-    
+
     @classmethod
     def _from_code(cls, space, code, hidden_applevel=False, code_hook=None):
         """ Initialize the code object from a real (CPython) one.
                       list(code.co_cellvars),
                       hidden_applevel, cpython_magic)
 
-    
+
     def _compute_flatcall(self):
         # Speed hack!
         self.fast_natural_arity = eval.Code.HOPELESS
             return
         if self.co_argcount > 0xff:
             return
-        
+
         self.fast_natural_arity = eval.Code.FLATPYCALL | self.co_argcount
 
     def funcrun(self, func, args):
                                       fresh_virtualizable=True)
         args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
                                              func.name,
-                                             sig, func.defs_w)
+                                             sig, func.defs.getitems())
         fresh_frame.init_cells()
         return frame.run()
 
         sig = self._signature
         # speed hack
         fresh_frame = jit.hint(frame, access_directly=True,
-                                      fresh_virtualizable=True)        
+                                      fresh_virtualizable=True)
         args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
                                              func.name,
-                                             sig, func.defs_w)
+                                             sig, func.defs.getitems())
         fresh_frame.init_cells()
         return frame.run()
 
 
     def fget_co_consts(self, space):
         return space.newtuple(self.co_consts_w)
-    
+
     def fget_co_names(self, space):
         return space.newtuple(self.co_names_w)
 
         return space.newtuple([space.wrap(name) for name in self.co_cellvars])
 
     def fget_co_freevars(self, space):
-        return space.newtuple([space.wrap(name) for name in self.co_freevars])    
+        return space.newtuple([space.wrap(name) for name in self.co_freevars])
 
     def descr_code__eq__(self, w_other):
         space = self.space
         new_inst = mod.get('code_new')
         w        = space.wrap
         tup      = [
-            w(self.co_argcount), 
-            w(self.co_nlocals), 
-            w(self.co_stacksize), 
+            w(self.co_argcount),
+            w(self.co_nlocals),
+            w(self.co_stacksize),
             w(self.co_flags),
-            w(self.co_code), 
-            space.newtuple(self.co_consts_w), 
-            space.newtuple(self.co_names_w), 
-            space.newtuple([w(v) for v in self.co_varnames]), 
+            w(self.co_code),
+            space.newtuple(self.co_consts_w),
+            space.newtuple(self.co_names_w),
+            space.newtuple([w(v) for v in self.co_varnames]),
             w(self.co_filename),
-            w(self.co_name), 
+            w(self.co_name),
             w(self.co_firstlineno),
-            w(self.co_lnotab), 
+            w(self.co_lnotab),
             space.newtuple([w(v) for v in self.co_freevars]),
             space.newtuple([w(v) for v in self.co_cellvars]),
             w(self.magic),

File pypy/interpreter/test/test_gateway.py

View file
 # -*- coding: utf-8 -*-
 
 from pypy.conftest import gettestobjspace
-from pypy.interpreter import gateway
+from pypy.interpreter import gateway, argument
 from pypy.interpreter.gateway import ObjSpace, W_Root
-from pypy.interpreter import argument
+from pypy.interpreter.function import Defaults
 import py
 import sys
 
 class FakeFunc(object):
-
     def __init__(self, space, name):
         self.space = space
         self.name = name
-        self.defs_w = []
+        self.defs = Defaults([])
 
-class TestBuiltinCode: 
+class TestBuiltinCode:
     def test_signature(self):
         def c(space, w_x, w_y, hello_w):
             pass
         w_result = code.funcrun(FakeFunc(self.space, "c"), args)
         assert self.space.eq_w(w_result, w(1020))
 
-class TestGateway: 
+class TestGateway:
 
     def test_app2interp(self):
         w = self.space.wrap
             return a+b
         g3 = gateway.app2interp_temp(noapp_g3, gateway.applevel_temp)
         assert self.space.eq_w(g3(self.space, w('foo'), w('bar')), w('foobar'))
-        
+
     def test_app2interp2(self):
         """same but using transformed code"""
         w = self.space.wrap
         def g3(space, w_a, w_b):
             return space.add(w_a, w_b)
         app_g3 = gateway.interp2app_temp(g3)
-        w_app_g3 = space.wrap(app_g3) 
+        w_app_g3 = space.wrap(app_g3)
         assert self.space.eq_w(
-            space.call(w_app_g3, 
+            space.call(w_app_g3,
                        space.newtuple([w('foo'), w('bar')]),
                        space.newdict()),
             w('foobar'))
         assert self.space.eq_w(
             space.call_function(w_app_g3, w('foo'), w('bar')),
             w('foobar'))
-        
+
     def test_interp2app_unwrap_spec(self):
         space = self.space
         w = space.wrap
         def g3(space, w_a, w_b):
-            return space.add(w_a, w_b)        
+            return space.add(w_a, w_b)
         app_g3 = gateway.interp2app_temp(g3,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       gateway.W_Root,
                                                       gateway.W_Root])
-        w_app_g3 = space.wrap(app_g3) 
+        w_app_g3 = space.wrap(app_g3)
         assert self.space.eq_w(
-            space.call(w_app_g3, 
+            space.call(w_app_g3,
                        space.newtuple([w('foo'), w('bar')]),
                        space.newdict()),
             w('foobar'))
         app_A = gateway.interp2app(A.f)
         app_B = gateway.interp2app(B.f)
         assert app_A is not app_B
-        
+
     def test_interp2app_unwrap_spec_nonnegint(self):
         space = self.space
         w = space.wrap
         space = self.space
         w = space.wrap
         def g3_args_w(space, args_w):
-            return space.add(args_w[0], args_w[1])        
+            return space.add(args_w[0], args_w[1])
         app_g3_args_w = gateway.interp2app_temp(g3_args_w,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       'args_w'])
-        w_app_g3_args_w = space.wrap(app_g3_args_w) 
+        w_app_g3_args_w = space.wrap(app_g3_args_w)
         assert self.space.eq_w(
-            space.call(w_app_g3_args_w, 
+            space.call(w_app_g3_args_w,
                        space.newtuple([w('foo'), w('bar')]),
                        space.newdict()),
             w('foobar'))
         def g3_ss(space, s0, s1):
             if s1 is None:
                 return space.wrap(42)
-            return space.wrap(s0+s1)       
+            return space.wrap(s0+s1)
         app_g3_ss = gateway.interp2app_temp(g3_ss,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       str, 'str_or_None'])
-        w_app_g3_ss = space.wrap(app_g3_ss) 
+        w_app_g3_ss = space.wrap(app_g3_ss)
         assert self.space.eq_w(
-            space.call(w_app_g3_ss, 
+            space.call(w_app_g3_ss,
                        space.newtuple([w('foo'), w('bar')]),
                        space.newdict()),
             w('foobar'))
         space = self.space
         w = space.wrap
         def g3_if(space, i0, f1):
-            return space.wrap(i0+f1)       
+            return space.wrap(i0+f1)
         app_g3_if = gateway.interp2app_temp(g3_if,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       int,float])
-        w_app_g3_if = space.wrap(app_g3_if) 
+        w_app_g3_if = space.wrap(app_g3_if)
         assert self.space.eq_w(
-            space.call(w_app_g3_if, 
+            space.call(w_app_g3_if,
                        space.newtuple([w(1), w(1.0)]),
                        space.newdict()),
             w(2.0))
         w_app_g3_ll = space.wrap(app_g3_ll)
         w_big = w(gateway.r_longlong(10**10))
         assert space.eq_w(
-            space.call(w_app_g3_ll, 
+            space.call(w_app_g3_ll,
                        space.newtuple([w_big]),
                        space.newdict()),
             w(gateway.r_longlong(3 * 10**10)))
         app_g3_idx = gateway.interp2app_temp(g3_idx,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       'index'])
-        w_app_g3_idx = space.wrap(app_g3_idx) 
+        w_app_g3_idx = space.wrap(app_g3_idx)
         assert space.eq_w(
             space.call_function(w_app_g3_idx, w(123)),
             w(124))
                                                       int])
         w_app_g3_i = space.wrap(app_g3_i)
         assert space.eq_w(space.call_function(w_app_g3_i,w(1)),w(1))
-        assert space.eq_w(space.call_function(w_app_g3_i,w(1L)),w(1))        
+        assert space.eq_w(space.call_function(w_app_g3_i,w(1L)),w(1))
         raises(gateway.OperationError,space.call_function,w_app_g3_i,w(sys.maxint*2))
         raises(gateway.OperationError,space.call_function,w_app_g3_i,w(None))
         raises(gateway.OperationError,space.call_function,w_app_g3_i,w("foo"))
         raises(gateway.OperationError,space.call_function,w_app_g3_s,w(None))
         raises(gateway.OperationError,space.call_function,w_app_g3_s,w(1))
         raises(gateway.OperationError,space.call_function,w_app_g3_s,w(1.0))
-        
+
         app_g3_f = gateway.interp2app_temp(g3_id,
                                          unwrap_spec=[gateway.ObjSpace,
                                                       float])
         w_app_g3_f = space.wrap(app_g3_f)
         assert space.eq_w(space.call_function(w_app_g3_f,w(1.0)),w(1.0))
         assert space.eq_w(space.call_function(w_app_g3_f,w(1)),w(1.0))
-        assert space.eq_w(space.call_function(w_app_g3_f,w(1L)),w(1.0))        
+        assert space.eq_w(space.call_function(w_app_g3_f,w(1L)),w(1.0))
         raises(gateway.OperationError,space.call_function,w_app_g3_f,w(None))
         raises(gateway.OperationError,space.call_function,w_app_g3_f,w("foo"))
 
             called.append(w_func)
             return fastcall_2(space, w_func, w_a, w_b)
 
-        w_app_f.code.fastcall_2 = witness_fastcall_2    
-    
+        w_app_f.code.fastcall_2 = witness_fastcall_2
+
         w_res = space.appexec([w_app_f, w_3], """(f, x):
         class A(object):
            m = f # not a builtin function, so works as method
         """)
 
         assert space.is_true(w_res)
-        assert called == [w_app_f, w_app_f]       
-        
+        assert called == [w_app_f, w_app_f]
+
     def test_plain(self):
         space = self.space
 
 
         w_res = space.call_args(w_g, args)
         assert space.is_true(space.eq(w_res, space.wrap(('g', -1, 0))))
-        
+
         w_self = space.wrap('self')
 
         args0 = argument.Arguments(space, [space.wrap(0)])
 
 
 class TestPassThroughArguments:
-    
+
     def test_pass_trough_arguments0(self):
         space = self.space
 
         called = []
-        
+
         def f(space, __args__):
             called.append(__args__)
             a_w, _ = __args__.unpack()
 
         w_res = space.call_args(w_f, args)
         assert space.is_true(space.eq(w_res, space.wrap(('f', 7))))
-        
+
         # white-box check for opt
         assert called[0] is args
 
         space = self.space
 
         called = []
-        
+
         def g(space, w_self, __args__):
             called.append(__args__)
             a_w, _ = __args__.unpack()
         w_res = space.call_args(w_g, args)
         assert space.is_true(space.eq(w_res, space.wrap(('g', 'self', 0))))
         # no opt in this case
-        assert len(called) == 2      
+        assert len(called) == 2
         assert called[0] == 'funcrun'
         called = []
 
         w_res = space.call_function(w_g, w_self)
         assert space.is_true(space.eq(w_res, space.wrap(('g', 'self'))))
         assert len(called) == 1
-        assert isinstance(called[0], argument.Arguments)        
+        assert isinstance(called[0], argument.Arguments)
         called = []
-        
+
         w_res = space.appexec([w_g], """(g):
         return g('self', 11)
         """)
         assert space.is_true(space.eq(w_res, space.wrap(('g', 'self', 11))))
         assert len(called) == 1
-        assert isinstance(called[0], argument.Arguments)                
+        assert isinstance(called[0], argument.Arguments)
         called = []
 
         w_res = space.appexec([w_g], """(g):
         clash = dict.__new__.func_code.co_varnames[0]
 
         dict(**{clash: 33})
-        dict.__new__(dict, **{clash: 33})        
+        dict.__new__(dict, **{clash: 33})
 
     def test_dict_init(self):
         d = {}
         clash = dict.update.func_code.co_varnames[0]
 
         d.update(**{clash: 33})
-        dict.update(d, **{clash: 33})        
-        
+        dict.update(d, **{clash: 33})
+

File pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py

View file
         where x and y can be either constants or variables. There are cases in
         which the second guard is proven to be always true.
         """
-        
+
         for a, b, res, opt_expected in (('2000', '2000', 20001000, True),
                                         ( '500',  '500', 15001500, True),
                                         ( '300',  '600', 16001700, False),
         test only checks that we get the expected result, not that any
         optimization has been applied.
         """
-        ops = ('<', '>', '<=', '>=', '==', '!=')        
+        ops = ('<', '>', '<=', '>=', '==', '!=')
         for op1 in ops:
             for op2 in ops:
                 for a,b in ((500, 500), (300, 600)):
         test only checks that we get the expected result, not that any
         optimization has been applied.
         """
-        ops = ('<', '>', '<=', '>=', '==', '!=')        
+        ops = ('<', '>', '<=', '>=', '==', '!=')
         for op1 in ops:
             for op2 in ops:
                 for a,b in ((500, 500), (300, 600)):
             --TICK--
             jump(p0, p1, p2, p3, p4, p5, p6, p7, i28, i15, i10, i11, descr=<Loop0>)
         """)
+
+    def test_func_defaults(self):
+        def main(n):
+            i = 1
+            while i < n:
+                i += len(xrange(i)) / i
+            return i
+
+        log = self.run(main, [10000])
+        assert log.result == 10000
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i10 = int_lt(i5, i6)
+            guard_true(i10, descr=<Guard3>)
+            # This can be improved if the JIT realized the lookup of i5 produces
+            # a constant and thus can be removed entirely
+            i12 = int_sub(i5, 1)
+            i13 = uint_floordiv(i12, i7)
+            i15 = int_add(i13, 1)
+            i17 = int_lt(i15, 0)
+            guard_false(i17, descr=<Guard4>)
+            i18 = int_floordiv(i15, i5)
+            i19 = int_xor(i15, i5)
+            i20 = int_mod(i15, i5)
+            i21 = int_is_true(i20)
+            i22 = int_add_ovf(i5, i18)
+            guard_no_overflow(descr=<Guard5>)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, i22, i6, i7, p8, p9, descr=<Loop0>)
+        """)

File pypy/objspace/std/fake.py

View file
         frame = func.space.createframe(self, func.w_func_globals,
                                         func.closure)
         sig = self.signature()
-        scope_w = args.parse_obj(None, func.name, sig, func.defs_w)
+        scope_w = args.parse_obj(None, func.name, sig, func.defs.getitems())
         frame.setfastscope(scope_w)
         return frame.run()
-    
+
 
 class CPythonFakeFrame(eval.Frame):