Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: faster-nested-scopes Changeset: r45649:29789b62e66d Date: 2011-07-15 19:32 +0200 http://bitbucket.org/pypy/pypy/changeset/29789b62e66d/
Log: make Function.closure a quasi-immutable array. Pass it into createframe, so that the reading of the cells is constant-folded. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -621,9 +621,9 @@ self.default_compiler = compiler return compiler - def createframe(self, code, w_globals, closure=None): + def createframe(self, code, w_globals, outer_func=None): "Create an empty PyFrame suitable for this code object." - return self.FrameClass(self, code, w_globals, closure) + return self.FrameClass(self, code, w_globals, outer_func) def allocate_lock(self): """Return an interp-level Lock object if threads are enabled, diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -30,7 +30,7 @@ can_change_code = True _immutable_fields_ = ['code?', 'w_func_globals?', - 'closure?', + 'closure?[*]', 'defs_w?[*]'] def __init__(self, space, code, w_globals=None, defs_w=[], closure=None, @@ -95,7 +95,7 @@ assert isinstance(code, PyCode) if nargs < 5: new_frame = self.space.createframe(code, self.w_func_globals, - self.closure) + self) for i in funccallunrolling: if i < nargs: new_frame.locals_stack_w[i] = args_w[i] @@ -155,7 +155,7 @@ def _flat_pycall(self, code, nargs, frame): # code is a PyCode new_frame = self.space.createframe(code, self.w_func_globals, - self.closure) + self) for i in xrange(nargs): w_arg = frame.peekvalue(nargs-1-i) new_frame.locals_stack_w[i] = w_arg @@ -166,7 +166,7 @@ def _flat_pycall_defaults(self, code, nargs, frame, defs_to_load): # code is a PyCode new_frame = self.space.createframe(code, self.w_func_globals, - self.closure) + self) for i in xrange(nargs): w_arg = frame.peekvalue(nargs-1-i) new_frame.locals_stack_w[i] = w_arg diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py --- a/pypy/interpreter/nestedscope.py +++ b/pypy/interpreter/nestedscope.py @@ -93,29 +93,31 @@ cells = None @jit.unroll_safe - def initialize_frame_scopes(self, closure, code): - super_initialize_frame_scopes(self, closure, code) + def initialize_frame_scopes(self, outer_func, code): + super_initialize_frame_scopes(self, outer_func, code) ncellvars = len(code.co_cellvars) nfreevars = len(code.co_freevars) if not nfreevars: if not ncellvars: return # no self.cells needed - fast path - if closure is None: - closure = [] - elif closure is None: + elif outer_func is None: space = self.space raise OperationError(space.w_TypeError, space.wrap("directly executed code object " "may not contain free variables")) - if len(closure) != nfreevars: + if outer_func and outer_func.closure: + closure_size = len(outer_func.closure) + else: + closure_size = 0 + if closure_size != nfreevars: raise ValueError("code object received a closure with " "an unexpected number of free variables") self.cells = [None] * (ncellvars + nfreevars) for i in range(ncellvars): self.cells[i] = Cell() for i in range(nfreevars): - self.cells[i + ncellvars] = closure[i] - + self.cells[i + ncellvars] = outer_func.closure[i] + def _getcells(self): return self.cells diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -198,7 +198,7 @@ def funcrun(self, func, args): frame = self.space.createframe(self, func.w_func_globals, - func.closure) + func) sig = self._signature # speed hack fresh_frame = jit.hint(frame, access_directly=True, @@ -211,7 +211,7 @@ def funcrun_obj(self, func, w_obj, args): frame = self.space.createframe(self, func.w_func_globals, - func.closure) + func) sig = self._signature # speed hack fresh_frame = jit.hint(frame, access_directly=True, diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py --- a/pypy/interpreter/pyframe.py +++ b/pypy/interpreter/pyframe.py @@ -51,7 +51,7 @@ is_being_profiled = False escaped = False # see mark_as_escaped() - def __init__(self, space, code, w_globals, closure): + def __init__(self, space, code, w_globals, outer_func): self = hint(self, access_directly=True, fresh_virtualizable=True) assert isinstance(code, pycode.PyCode) self.pycode = code @@ -67,7 +67,7 @@ self.builtin = space.builtin.pick_builtin(w_globals) # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. # class bodies only have CO_NEWLOCALS. - self.initialize_frame_scopes(closure, code) + self.initialize_frame_scopes(outer_func, code) self.f_lineno = code.co_firstlineno def mark_as_escaped(self): @@ -113,8 +113,8 @@ return self.builtin else: return self.space.builtin - - def initialize_frame_scopes(self, closure, code): + + def initialize_frame_scopes(self, outer_func, code): # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. # class bodies only have CO_NEWLOCALS. # CO_NEWLOCALS: make a locals dict unless optimized is also set @@ -381,7 +381,11 @@ # do not use the instance's __init__ but the base's, because we set # everything like cells from here - PyFrame.__init__(self, space, pycode, w_globals, closure) + # XXX hack + from pypy.interpreter.function import Function + outer_func = Function(space, None, closure=closure, + forcename="") + PyFrame.__init__(self, space, pycode, w_globals, outer_func) f_back = space.interp_w(PyFrame, w_f_back, can_be_None=True) new_frame.f_backref = jit.non_virtual_ref(f_back) diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -293,7 +293,7 @@ raise break new_frame = space.createframe(code, w_func.w_func_globals, - w_func.closure) + w_func) new_frame.locals_stack_w[0] = w_item w_res = new_frame.run() result_w.append(w_res) diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py --- a/pypy/objspace/std/fake.py +++ b/pypy/objspace/std/fake.py @@ -142,7 +142,7 @@ def funcrun(self, func, args): frame = func.space.createframe(self, func.w_func_globals, - func.closure) + func) sig = self.signature() scope_w = args.parse_obj(None, func.name, sig, func.defs_w) frame.setfastscope(scope_w) diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -130,12 +130,12 @@ ec._py_repr = None return ec - def createframe(self, code, w_globals, closure=None): + def createframe(self, code, w_globals, outer_func=None): from pypy.objspace.std.fake import CPythonFakeCode, CPythonFakeFrame if not we_are_translated() and isinstance(code, CPythonFakeCode): return CPythonFakeFrame(self, code, w_globals) else: - return ObjSpace.createframe(self, code, w_globals, closure) + return ObjSpace.createframe(self, code, w_globals, outer_func) def gettypefor(self, cls): return self.gettypeobject(cls.typedef) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit