[pypy-svn] r68846 - in pypy/trunk/pypy: interpreter interpreter/test objspace
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Oct 29 15:58:17 CET 2009
Author: cfbolz
Date: Thu Oct 29 15:58:17 2009
New Revision: 68846
Modified:
pypy/trunk/pypy/interpreter/function.py
pypy/trunk/pypy/interpreter/gateway.py
pypy/trunk/pypy/interpreter/test/test_function.py
pypy/trunk/pypy/objspace/descroperation.py
Log:
Make it impossible to change the code object of builtin functions. This gets rid
of a getfield and a guard for all builtin function calls.
Modified: pypy/trunk/pypy/interpreter/function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/function.py (original)
+++ pypy/trunk/pypy/interpreter/function.py Thu Oct 29 15:58:17 2009
@@ -16,12 +16,20 @@
funccallunrolling = unrolling_iterable(range(4))
+ at jit.purefunction
+def _get_immutable_code(func):
+ assert not func.can_change_code
+ return func.code
+
class Function(Wrappable):
"""A function is a code object captured with some environment:
an object space, a dictionary of globals, default arguments,
and an arbitrary 'closure' passed to the code object."""
- def __init__(self, space, code, w_globals=None, defs_w=[], closure=None, forcename=None):
+ can_change_code = True
+
+ def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
+ forcename=None):
self.space = space
self.name = forcename or code.co_name
self.w_doc = None # lazily read from code.getdocstring()
@@ -48,7 +56,12 @@
return self.getcode().funcrun_obj(self, w_obj, args)
def getcode(self):
- return jit.hint(self.code, promote=True)
+ if jit.we_are_jitted():
+ if not self.can_change_code:
+ self = jit.hint(self, promote=True)
+ return _get_immutable_code(self)
+ return jit.hint(self.code, promote=True)
+ return self.code
def funccall(self, *args_w): # speed hack
from pypy.interpreter import gateway
@@ -368,6 +381,9 @@
def fset_func_code(space, self, w_code):
from pypy.interpreter.pycode import PyCode
+ if not self.can_change_code:
+ raise OperationError(space.w_TypeError,
+ space.wrap("Cannot change code attribute of builtin functions"))
code = space.interp_w(Code, w_code)
closure_len = 0
if self.closure:
@@ -568,7 +584,11 @@
"'%s' object is not callable" % typename))
return space.wrap(ClassMethod(w_function))
+class FunctionWithFixedCode(Function):
+ can_change_code = False
+
class BuiltinFunction(Function):
+ can_change_code = False
def __init__(self, func):
assert isinstance(func, Function)
Modified: pypy/trunk/pypy/interpreter/gateway.py
==============================================================================
--- pypy/trunk/pypy/interpreter/gateway.py (original)
+++ pypy/trunk/pypy/interpreter/gateway.py Thu Oct 29 15:58:17 2009
@@ -16,6 +16,7 @@
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.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
from pypy.interpreter.baseobjspace import Wrappable, SpaceCache, DescrMismatch
from pypy.interpreter.argument import Arguments, Signature
@@ -788,7 +789,7 @@
space = cache.space
defs = gateway._getdefaults(space) # needs to be implemented by subclass
code = gateway._code
- fn = Function(space, code, None, defs, forcename = gateway.name)
+ fn = FunctionWithFixedCode(space, code, None, defs, forcename = gateway.name)
if not space.config.translating: # for tests and py.py
fn._freeze_()
if gateway.as_classmethod:
Modified: pypy/trunk/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_function.py (original)
+++ pypy/trunk/pypy/interpreter/test/test_function.py Thu Oct 29 15:58:17 2009
@@ -84,6 +84,11 @@
return f() # a closure
raises(ValueError, "f.func_code = h.func_code")
+ def test_write_code_builtin_forbidden(self):
+ def f(*args):
+ return 42
+ raises(TypeError, "dir.func_code = f.func_code")
+ raises(TypeError, "list.append.im_func.func_code = f.func_code")
class AppTestFunction:
Modified: pypy/trunk/pypy/objspace/descroperation.py
==============================================================================
--- pypy/trunk/pypy/objspace/descroperation.py (original)
+++ pypy/trunk/pypy/objspace/descroperation.py Thu Oct 29 15:58:17 2009
@@ -90,9 +90,7 @@
def get_and_call_function(space, w_descr, w_obj, *args_w):
descr = space.interpclass_w(w_descr)
# a special case for performance and to avoid infinite recursion
- if type(descr) is Function:
- # the fastcall paths are purely for performance, but the resulting
- # increase of speed is huge
+ if isinstance(descr, Function):
return descr.funccall(w_obj, *args_w)
else:
args = Arguments(space, list(args_w))
More information about the Pypy-commit
mailing list