[pypy-svn] r80004 - in pypy/branch/fast-forward: lib-python/modified-2.5.2/encodings lib-python/modified-2.5.2/test lib-python/modified-2.5.2/test/output lib_pypy/_ctypes pypy/config pypy/doc/config pypy/interpreter pypy/interpreter/pyparser pypy/interpreter/pyparser/test pypy/interpreter/test pypy/jit/backend/llsupport pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/module/_lsprof pypy/module/_lsprof/test pypy/module/cpyext pypy/module/cpyext/src pypy/module/exceptions pypy/module/imp pypy/module/posix pypy/module/posix/test pypy/module/select pypy/module/sys pypy/module/test_lib_pypy/ctypes_tests pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory/gc pypy/rpython/memory/gctransform pypy/rpython/module pypy/translator/c/test pypy/translator/goal pypy/translator/sandbox/test
afa at codespeak.net
afa at codespeak.net
Sun Dec 12 18:11:25 CET 2010
Author: afa
Date: Sun Dec 12 18:11:19 2010
New Revision: 80004
Added:
pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_eof.py
- copied unchanged from r80002, pypy/trunk/lib-python/modified-2.5.2/test/test_eof.py
pypy/branch/fast-forward/pypy/doc/config/translation.jit_ffi.txt
- copied unchanged from r80002, pypy/trunk/pypy/doc/config/translation.jit_ffi.txt
pypy/branch/fast-forward/pypy/module/cpyext/pypyintf.py
- copied unchanged from r80002, pypy/trunk/pypy/module/cpyext/pypyintf.py
pypy/branch/fast-forward/pypy/translator/goal/targetsha1sum.py
- copied unchanged from r80002, pypy/trunk/pypy/translator/goal/targetsha1sum.py
Removed:
pypy/branch/fast-forward/lib-python/modified-2.5.2/encodings/
Modified:
pypy/branch/fast-forward/lib-python/modified-2.5.2/test/output/test_cProfile
pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_genexps.py
pypy/branch/fast-forward/lib_pypy/_ctypes/primitive.py
pypy/branch/fast-forward/pypy/config/pypyoption.py
pypy/branch/fast-forward/pypy/config/translationoption.py
pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
pypy/branch/fast-forward/pypy/interpreter/executioncontext.py
pypy/branch/fast-forward/pypy/interpreter/function.py
pypy/branch/fast-forward/pypy/interpreter/mixedmodule.py
pypy/branch/fast-forward/pypy/interpreter/pyparser/error.py
pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenizer.py
pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_pyparse.py
pypy/branch/fast-forward/pypy/interpreter/test/test_compiler.py
pypy/branch/fast-forward/pypy/interpreter/test/test_executioncontext.py
pypy/branch/fast-forward/pypy/interpreter/test/test_function.py
pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py
pypy/branch/fast-forward/pypy/jit/metainterp/compile.py
pypy/branch/fast-forward/pypy/jit/metainterp/graphpage.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py
pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py
pypy/branch/fast-forward/pypy/jit/metainterp/test/test_fficall.py
pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefficall.py
pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py
pypy/branch/fast-forward/pypy/module/_lsprof/interp_lsprof.py
pypy/branch/fast-forward/pypy/module/_lsprof/test/test_cprofile.py
pypy/branch/fast-forward/pypy/module/cpyext/__init__.py
pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c
pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py
pypy/branch/fast-forward/pypy/module/imp/importing.py
pypy/branch/fast-forward/pypy/module/posix/__init__.py
pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py
pypy/branch/fast-forward/pypy/module/select/interp_select.py
pypy/branch/fast-forward/pypy/module/sys/vm.py
pypy/branch/fast-forward/pypy/module/test_lib_pypy/ctypes_tests/test_cast.py
pypy/branch/fast-forward/pypy/objspace/std/complexobject.py
pypy/branch/fast-forward/pypy/objspace/std/complextype.py
pypy/branch/fast-forward/pypy/objspace/std/floattype.py
pypy/branch/fast-forward/pypy/objspace/std/longobject.py
pypy/branch/fast-forward/pypy/objspace/std/strutil.py
pypy/branch/fast-forward/pypy/objspace/std/test/test_complexobject.py
pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py
pypy/branch/fast-forward/pypy/rlib/rmd5.py
pypy/branch/fast-forward/pypy/rlib/rmmap.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llarena.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/env.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/minimark.py
pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py
pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py
pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py
Log:
Merge from trunk:
svn merge -r79849:80002 ../trunk
Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/test/output/test_cProfile
==============================================================================
--- pypy/branch/fast-forward/lib-python/modified-2.5.2/test/output/test_cProfile (original)
+++ pypy/branch/fast-forward/lib-python/modified-2.5.2/test/output/test_cProfile Sun Dec 12 18:11:19 2010
@@ -14,66 +14,66 @@
4 0.116 0.029 0.120 0.030 test_cProfile.py:78(helper1)
2 0.000 0.000 0.140 0.070 test_cProfile.py:89(helper2_indirect)
8 0.312 0.039 0.400 0.050 test_cProfile.py:93(helper2)
- 4 0.000 0.000 0.000 0.000 {append}
- 1 0.000 0.000 0.000 0.000 {disable}
12 0.000 0.000 0.012 0.001 {hasattr}
+ 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
+ 1 0.000 0.000 0.000 0.000 {method 'disable' of 'Profile' objects}
8 0.000 0.000 0.000 0.000 {range}
4 0.000 0.000 0.000 0.000 {sys.exc_info}
Ordered by: standard name
-Function called...
- ncalls tottime cumtime
-<string>:1(<module>) -> 1 0.270 1.000 test_cProfile.py:30(testfunc)
-test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__)
- 8 0.000 0.000 {range}
-test_cProfile.py:115(__getattr__) ->
-test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial)
- 2 0.040 0.600 test_cProfile.py:60(helper)
-test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial)
- 20 0.020 0.020 test_cProfile.py:53(mul)
-test_cProfile.py:53(mul) ->
-test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1)
- 2 0.000 0.140 test_cProfile.py:89(helper2_indirect)
- 6 0.234 0.300 test_cProfile.py:93(helper2)
-test_cProfile.py:78(helper1) -> 4 0.000 0.000 {append}
- 4 0.000 0.004 {hasattr}
- 4 0.000 0.000 {sys.exc_info}
-test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial)
- 2 0.078 0.100 test_cProfile.py:93(helper2)
-test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper)
- 8 0.000 0.008 {hasattr}
-{append} ->
-{disable} ->
-{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__)
-{range} ->
-{sys.exc_info} ->
+Function called...
+ ncalls tottime cumtime
+<string>:1(<module>) -> 1 0.270 1.000 test_cProfile.py:30(testfunc)
+test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__)
+ 8 0.000 0.000 {range}
+test_cProfile.py:115(__getattr__) ->
+test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial)
+ 2 0.040 0.600 test_cProfile.py:60(helper)
+test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial)
+ 20 0.020 0.020 test_cProfile.py:53(mul)
+test_cProfile.py:53(mul) ->
+test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1)
+ 2 0.000 0.140 test_cProfile.py:89(helper2_indirect)
+ 6 0.234 0.300 test_cProfile.py:93(helper2)
+test_cProfile.py:78(helper1) -> 4 0.000 0.004 {hasattr}
+ 4 0.000 0.000 {method 'append' of 'list' objects}
+ 4 0.000 0.000 {sys.exc_info}
+test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial)
+ 2 0.078 0.100 test_cProfile.py:93(helper2)
+test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper)
+ 8 0.000 0.008 {hasattr}
+{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__)
+{method 'append' of 'list' objects} ->
+{method 'disable' of 'Profile' objects} ->
+{range} ->
+{sys.exc_info} ->
Ordered by: standard name
-Function was called by...
- ncalls tottime cumtime
-<string>:1(<module>) <-
-test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2)
-test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper)
- 12 0.012 0.012 {hasattr}
-test_cProfile.py:30(testfunc) <- 1 0.270 1.000 <string>:1(<module>)
-test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc)
- 20/3 0.130 0.147 test_cProfile.py:40(factorial)
- 2 0.006 0.040 test_cProfile.py:89(helper2_indirect)
-test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial)
-test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc)
-test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper)
-test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper)
-test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper)
- 2 0.078 0.100 test_cProfile.py:89(helper2_indirect)
-{append} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
-{disable} <-
-{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1)
- 8 0.000 0.008 test_cProfile.py:93(helper2)
-{range} <- 8 0.000 0.000 test_cProfile.py:103(subhelper)
-{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
+Function was called by...
+ ncalls tottime cumtime
+<string>:1(<module>) <-
+test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2)
+test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper)
+ 12 0.012 0.012 {hasattr}
+test_cProfile.py:30(testfunc) <- 1 0.270 1.000 <string>:1(<module>)
+test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc)
+ 20/3 0.130 0.147 test_cProfile.py:40(factorial)
+ 2 0.006 0.040 test_cProfile.py:89(helper2_indirect)
+test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial)
+test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc)
+test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper)
+test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper)
+test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper)
+ 2 0.078 0.100 test_cProfile.py:89(helper2_indirect)
+{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1)
+ 8 0.000 0.008 test_cProfile.py:93(helper2)
+{method 'append' of 'list' objects} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
+{method 'disable' of 'Profile' objects} <-
+{range} <- 8 0.000 0.000 test_cProfile.py:103(subhelper)
+{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_genexps.py
==============================================================================
--- pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_genexps.py (original)
+++ pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_genexps.py Sun Dec 12 18:11:19 2010
@@ -77,10 +77,10 @@
Verify that parenthesis are required in a statement
>>> def f(n):
- ... return i*i for i in xrange(n)
+ ... return i*i for i in xrange(n) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
- SyntaxError: invalid syntax
+ SyntaxError: invalid syntax...
Verify that parenthesis are required when used as a keyword argument value
Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/primitive.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/primitive.py (original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/primitive.py Sun Dec 12 18:11:19 2010
@@ -295,9 +295,9 @@
self.value = value
def _ensure_objects(self):
- if self._type_ in 'zZ':
- return self._objects
- return None
+ if self._type_ not in 'zZP':
+ assert self._objects is None
+ return self._objects
def _getvalue(self):
return self._buffer[0]
Modified: pypy/branch/fast-forward/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/pypyoption.py (original)
+++ pypy/branch/fast-forward/pypy/config/pypyoption.py Sun Dec 12 18:11:19 2010
@@ -78,6 +78,7 @@
"_rawffi": [("objspace.usemodules.struct", True)],
"cpyext": [("translation.secondaryentrypoints", "cpyext"),
("translation.shared", sys.platform == "win32")],
+ "_ffi": [("translation.jit_ffi", True)],
}
module_import_dependencies = {
Modified: pypy/branch/fast-forward/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/translationoption.py (original)
+++ pypy/branch/fast-forward/pypy/config/translationoption.py Sun Dec 12 18:11:19 2010
@@ -117,6 +117,7 @@
ChoiceOption("jit_profiler", "integrate profiler support into the JIT",
["off", "oprofile"],
default="off"),
+ BoolOption("jit_ffi", "optimize libffi calls", default=False),
# misc
BoolOption("verbose", "Print extra information", default=False),
Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Sun Dec 12 18:11:19 2010
@@ -865,14 +865,14 @@
def call_args_and_c_profile(self, frame, w_func, args):
ec = self.getexecutioncontext()
- ec.c_call_trace(frame, w_func)
+ ec.c_call_trace(frame, w_func, args)
try:
w_res = self.call_args(w_func, args)
except OperationError, e:
w_value = e.get_w_value(self)
ec.c_exception_trace(frame, w_value)
raise
- ec.c_return_trace(frame, w_func)
+ ec.c_return_trace(frame, w_func, args)
return w_res
def call_method(self, w_obj, methname, *arg_w):
@@ -1182,6 +1182,27 @@
self.wrap("expected a 32-bit integer"))
return value
+ def c_filedescriptor_w(self, w_fd):
+ try:
+ fd = self.c_int_w(w_fd)
+ except OperationError, e:
+ if not e.match(self, self.w_TypeError):
+ raise
+ try:
+ w_fileno = self.getattr(w_fd, self.wrap('fileno'))
+ except OperationError, e:
+ if e.match(self, self.w_AttributeError):
+ raise OperationError(self.w_TypeError,
+ self.wrap("argument must be an int, "
+ "or have a fileno() method."))
+ raise
+ w_fd = self.call_function(w_fileno)
+ fd = self.c_int_w(w_fd)
+ if fd < 0:
+ raise operationerrfmt(self.w_ValueError,
+ "file descriptor cannot be a negative integer (%d)", fd)
+ return fd
+
def warn(self, msg, w_warningcls):
self.appexec([self.wrap(msg), w_warningcls], """(msg, warningcls):
import warnings
Modified: pypy/branch/fast-forward/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/executioncontext.py Sun Dec 12 18:11:19 2010
@@ -123,19 +123,30 @@
return lst
# coroutine: I think this is all, folks!
- def c_call_trace(self, frame, w_func):
+ def c_call_trace(self, frame, w_func, args=None):
"Profile the call of a builtin function"
- if self.profilefunc is None:
- frame.is_being_profiled = False
- else:
- self._trace(frame, 'c_call', w_func)
+ self._c_call_return_trace(frame, w_func, args, 'c_call')
- def c_return_trace(self, frame, w_retval):
+ def c_return_trace(self, frame, w_func, args=None):
"Profile the return from a builtin function"
+ self._c_call_return_trace(frame, w_func, args, 'c_return')
+
+ def _c_call_return_trace(self, frame, w_func, args, event):
if self.profilefunc is None:
frame.is_being_profiled = False
else:
- self._trace(frame, 'c_return', w_retval)
+ # undo the effect of the CALL_METHOD bytecode, which would be
+ # that even on a built-in method call like '[].append()',
+ # w_func is actually the unbound function 'append'.
+ from pypy.interpreter.function import FunctionWithFixedCode
+ if isinstance(w_func, FunctionWithFixedCode) and args is not None:
+ w_firstarg = args.firstarg()
+ if w_firstarg is not None:
+ from pypy.interpreter.function import descr_function_get
+ w_func = descr_function_get(self.space, w_func, w_firstarg,
+ self.space.type(w_firstarg))
+ #
+ self._trace(frame, event, w_func)
def c_exception_trace(self, frame, w_exc):
"Profile function called upon OperationError."
Modified: pypy/branch/fast-forward/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/function.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/function.py Sun Dec 12 18:11:19 2010
@@ -48,7 +48,7 @@
return "<%s %s>" % (self.__class__.__name__, name)
def call_args(self, args):
- # delegate activation to code
+ # delegate activation to code
return self.getcode().funcrun(self, args)
def call_obj_args(self, w_obj, args):
@@ -61,17 +61,17 @@
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
from pypy.interpreter.pycode import PyCode
-
+
code = self.getcode() # hook for the jit
nargs = len(args_w)
fast_natural_arity = code.fast_natural_arity
if nargs == fast_natural_arity:
if nargs == 0:
- assert isinstance(code, gateway.BuiltinCode0)
+ assert isinstance(code, gateway.BuiltinCode0)
return code.fastcall_0(self.space, self)
elif nargs == 1:
assert isinstance(code, gateway.BuiltinCode1)
@@ -80,22 +80,22 @@
assert isinstance(code, gateway.BuiltinCode2)
return code.fastcall_2(self.space, self, args_w[0], args_w[1])
elif nargs == 3:
- assert isinstance(code, gateway.BuiltinCode3)
+ assert isinstance(code, gateway.BuiltinCode3)
return code.fastcall_3(self.space, self, args_w[0],
args_w[1], args_w[2])
elif nargs == 4:
- assert isinstance(code, gateway.BuiltinCode4)
+ 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:
- assert isinstance(code, PyCode)
+ assert isinstance(code, PyCode)
if nargs < 5:
new_frame = self.space.createframe(code, self.w_func_globals,
self.closure)
for i in funccallunrolling:
if i < nargs:
new_frame.fastlocals_w[i] = args_w[i]
- return new_frame.run()
+ return new_frame.run()
elif nargs >= 1 and fast_natural_arity == Code.PASSTHROUGHARGS1:
assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
return code.funcrun_obj(self, args_w[0],
@@ -106,9 +106,9 @@
def funccall_valuestack(self, nargs, frame): # speed hack
from pypy.interpreter import gateway
from pypy.interpreter.pycode import PyCode
-
+
code = self.getcode() # hook for the jit
- fast_natural_arity = code.fast_natural_arity
+ fast_natural_arity = code.fast_natural_arity
if nargs == fast_natural_arity:
if nargs == 0:
assert isinstance(code, gateway.BuiltinCode0)
@@ -143,7 +143,7 @@
w_obj = frame.peekvalue(nargs-1)
args = frame.make_arguments(nargs-1)
return code.funcrun_obj(self, w_obj, args)
-
+
args = frame.make_arguments(nargs)
return self.call_args(args)
@@ -155,8 +155,8 @@
for i in xrange(nargs):
w_arg = frame.peekvalue(nargs-1-i)
new_frame.fastlocals_w[i] = w_arg
-
- return new_frame.run()
+
+ return new_frame.run()
@jit.unroll_safe
def _flat_pycall_defaults(self, code, nargs, frame, defs_to_load):
@@ -166,7 +166,7 @@
for i in xrange(nargs):
w_arg = frame.peekvalue(nargs-1-i)
new_frame.fastlocals_w[i] = w_arg
-
+
defs_w = self.defs_w
ndefs = len(defs_w)
start = ndefs-defs_to_load
@@ -174,7 +174,7 @@
for j in xrange(start, ndefs):
new_frame.fastlocals_w[i] = defs_w[j]
i += 1
- return new_frame.run()
+ return new_frame.run()
def getdict(self):
if self.w_func_dict is None:
@@ -188,7 +188,7 @@
# unwrapping is done through unwrap_specs in typedef.py
- def descr_function__new__(space, w_subtype, w_code, w_globals,
+ def descr_function__new__(space, w_subtype, w_code, w_globals,
w_name=None, w_argdefs=None, w_closure=None):
code = space.interp_w(Code, w_code)
if not space.is_true(space.isinstance(w_globals, space.w_dict)):
@@ -229,7 +229,7 @@
return self.getrepr(self.space, 'function %s' % (self.name,))
- # delicate
+ # delicate
_all = {'': None}
def _freeze_(self):
@@ -260,7 +260,7 @@
new_inst = mod.get('builtin_function')
return space.newtuple([new_inst,
space.newtuple([space.wrap(code.identifier)])])
-
+
new_inst = mod.get('func_new')
w = space.wrap
if self.closure is None:
@@ -524,7 +524,7 @@
space = self.space
other = space.interpclass_w(w_other)
if not isinstance(other, Method):
- return space.w_False
+ return space.w_NotImplemented
if self.w_instance is None:
if other.w_instance is not None:
return space.w_False
@@ -562,7 +562,7 @@
else:
tup = [self.w_function, w_instance, self.w_class]
return space.newtuple([new_inst, space.newtuple(tup)])
-
+
class StaticMethod(Wrappable):
"""The staticmethod objects."""
_immutable_ = True
Modified: pypy/branch/fast-forward/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/mixedmodule.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/mixedmodule.py Sun Dec 12 18:11:19 2010
@@ -13,6 +13,10 @@
applevel_name = None
expose__file__attribute = True
+
+ # The following attribute is None as long as the module has not been
+ # imported yet, and when it has been, it is mod.__dict__.items() just
+ # after startup().
w_initialdict = None
def __init__(self, space, w_name):
@@ -26,8 +30,14 @@
"""This is called each time the module is imported or reloaded
"""
if self.w_initialdict is not None:
+ # the module was already imported. Refresh its content with
+ # the saved dict, as done with built-in and extension modules
+ # on CPython.
space.call_method(self.w_dict, 'update', self.w_initialdict)
- Module.init(self, space)
+ else:
+ Module.init(self, space)
+ if not self.lazy and self.w_initialdict is None:
+ self.w_initialdict = space.call_method(self.w_dict, 'items')
def get_applevel_name(cls):
""" NOT_RPYTHON """
@@ -96,6 +106,7 @@
def _freeze_(self):
self.getdict()
+ self.w_initialdict = None
self.startup_called = False
# hint for the annotator: Modules can hold state, so they are
# not constant
Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/error.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/pyparser/error.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/pyparser/error.py Sun Dec 12 18:11:19 2010
@@ -2,19 +2,22 @@
class SyntaxError(Exception):
"""Base class for exceptions raised by the parser."""
- def __init__(self, msg, lineno=0, offset=0, text=None, filename=None):
+ def __init__(self, msg, lineno=0, offset=0, text=None, filename=None,
+ lastlineno=0):
self.msg = msg
self.lineno = lineno
self.offset = offset
self.text = text
self.filename = filename
+ self.lastlineno = lastlineno
def wrap_info(self, space):
return space.newtuple([space.wrap(self.msg),
space.newtuple([space.wrap(self.filename),
space.wrap(self.lineno),
space.wrap(self.offset),
- space.wrap(self.text)])])
+ space.wrap(self.text),
+ space.wrap(self.lastlineno)])])
def __str__(self):
return "%s at pos (%d, %d) in %r" % (self.__class__.__name__,
@@ -33,8 +36,9 @@
class TokenError(SyntaxError):
- def __init__(self, msg, line, lineno, column, tokens):
- SyntaxError.__init__(self, msg, lineno, column, line)
+ def __init__(self, msg, line, lineno, column, tokens, lastlineno=0):
+ SyntaxError.__init__(self, msg, lineno, column, line,
+ lastlineno=lastlineno)
self.tokens = tokens
class TokenIndentationError(IndentationError):
Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenizer.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenizer.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenizer.py Sun Dec 12 18:11:19 2010
@@ -78,6 +78,7 @@
contline = None
indents = [0]
last_comment = ''
+ parenlevstart = (0, 0, "")
# make the annotator happy
endDFA = automata.DFA([], [])
@@ -85,7 +86,7 @@
line = ''
pos = 0
lines.append("")
- strstart = (0, 0)
+ strstart = (0, 0, "")
for line in lines:
lnum = lnum + 1
pos, max = 0, len(line)
@@ -94,7 +95,8 @@
if not line:
raise TokenError(
"EOF while scanning triple-quoted string literal",
- line, lnum-1, 0, token_list)
+ strstart[2], strstart[0], strstart[1]+1,
+ token_list, lnum)
endmatch = endDFA.recognize(line)
if endmatch >= 0:
pos = end = endmatch
@@ -147,6 +149,10 @@
else: # continued statement
if not line:
+ if parenlev > 0:
+ lnum1, start1, line1 = parenlevstart
+ raise TokenError("parenthesis is never closed", line1,
+ lnum1, start1 + 1, token_list, lnum)
raise TokenError("EOF in multi-line statement", line,
lnum, 0, token_list)
continued = 0
@@ -188,7 +194,7 @@
token_list.append(tok)
last_comment = ''
else:
- strstart = (lnum, start)
+ strstart = (lnum, start, line)
contstr = line[start:]
contline = line
break
@@ -196,7 +202,7 @@
token[:2] in single_quoted or \
token[:3] in single_quoted:
if token[-1] == '\n': # continued string
- strstart = (lnum, start)
+ strstart = (lnum, start, line)
endDFA = (endDFAs[initial] or endDFAs[token[1]] or
endDFAs[token[2]])
contstr, needcont = line[start:], 1
@@ -213,6 +219,8 @@
continued = 1
else:
if initial in '([{':
+ if parenlev == 0:
+ parenlevstart = (lnum, start, line)
parenlev = parenlev + 1
elif initial in ')]}':
parenlev = parenlev - 1
@@ -231,7 +239,7 @@
start = pos
if start<max and line[start] in single_quoted:
raise TokenError("EOL while scanning string literal",
- line, lnum, start, token_list)
+ line, lnum, start+1, token_list)
tok = (tokens.ERRORTOKEN, line[pos], lnum, pos, line)
token_list.append(tok)
last_comment = ''
Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_pyparse.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_pyparse.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_pyparse.py Sun Dec 12 18:11:19 2010
@@ -68,12 +68,21 @@
assert exc.lineno == 1
assert exc.offset == 5
assert exc.text.startswith("name another for")
- exc = py.test.raises(SyntaxError, parse, "\"blah").value
+ exc = py.test.raises(SyntaxError, parse, "x = \"blah\n\n\n").value
assert exc.msg == "EOL while scanning string literal"
- exc = py.test.raises(SyntaxError, parse, "'''\n").value
+ assert exc.lineno == 1
+ assert exc.offset == 5
+ exc = py.test.raises(SyntaxError, parse, "x = '''\n\n\n").value
assert exc.msg == "EOF while scanning triple-quoted string literal"
+ assert exc.lineno == 1
+ assert exc.offset == 5
for input in ("())", "(()", "((", "))"):
py.test.raises(SyntaxError, parse, input)
+ exc = py.test.raises(SyntaxError, parse, "x = (\n\n(),\n(),").value
+ assert exc.msg == "parenthesis is never closed"
+ assert exc.lineno == 1
+ assert exc.offset == 5
+ assert exc.lastlineno == 5
def test_is(self):
self.parse("x is y")
@@ -95,6 +104,7 @@
input = "def f():\n pass\n next_stmt"
exc = py.test.raises(IndentationError, parse, input).value
assert exc.msg == "unindent does not match any outer indentation level"
+ assert exc.lineno == 3
def test_mac_newline(self):
self.parse("this_is\ra_mac\rfile")
Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_compiler.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_compiler.py Sun Dec 12 18:11:19 2010
@@ -68,6 +68,17 @@
space.raises_w(space.w_SyntaxError, self.compiler.compile_command,
'if 1:\n x\n y\n', '?', 'exec', 0)
+ def test_syntaxerror_attrs(self):
+ w_args = self.space.appexec([], r"""():
+ try:
+ exec 'if 1:\n x\n y\n'
+ except SyntaxError, e:
+ return e.args
+ """)
+ assert self.space.unwrap(w_args) == (
+ 'unindent does not match any outer indentation level',
+ (None, 3, 0, ' y\n'))
+
def test_getcodeflags(self):
code = self.compiler.compile('from __future__ import division\n',
'<hello>', 'exec', 0)
@@ -918,3 +929,25 @@
assert e.msg == 'unindent does not match any outer indentation level'
else:
raise Exception("DID NOT RAISE")
+
+
+ def test_repr_vs_str(self):
+ source1 = "x = (\n"
+ source2 = "x = (\n\n"
+ try:
+ exec source1
+ except SyntaxError, err1:
+ pass
+ else:
+ raise Exception("DID NOT RAISE")
+ try:
+ exec source2
+ except SyntaxError, err2:
+ pass
+ else:
+ raise Exception("DID NOT RAISE")
+ assert str(err1) != str(err2)
+ assert repr(err1) != repr(err2)
+ err3 = eval(repr(err1))
+ assert str(err3) == str(err1)
+ assert repr(err3) == repr(err1)
Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_executioncontext.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_executioncontext.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_executioncontext.py Sun Dec 12 18:11:19 2010
@@ -7,6 +7,10 @@
class TestExecutionContext:
+ keywords = {}
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(**cls.keywords)
def test_action(self):
@@ -77,29 +81,43 @@
assert l == ['call', 'return', 'call', 'return']
def test_llprofile_c_call(self):
+ from pypy.interpreter.function import Function, Method
l = []
+ seen = []
+ space = self.space
- def profile_func(space, w_arg, frame, event, w_aarg):
+ def profile_func(space, w_arg, frame, event, w_func):
assert w_arg is space.w_None
l.append(event)
+ if event == 'c_call':
+ seen.append(w_func)
- space = self.space
- space.getexecutioncontext().setllprofile(profile_func, space.w_None)
-
- def check_snippet(snippet):
+ def check_snippet(snippet, expected_c_call):
+ del l[:]
+ del seen[:]
+ space.getexecutioncontext().setllprofile(profile_func,
+ space.w_None)
space.appexec([], """():
%s
return
""" % snippet)
space.getexecutioncontext().setllprofile(None, None)
assert l == ['call', 'return', 'call', 'c_call', 'c_return', 'return']
-
- check_snippet('l = []; l.append(42)')
- check_snippet('max(1, 2)')
- check_snippet('args = (1, 2); max(*args)')
- check_snippet('max(1, 2, **{})')
- check_snippet('args = (1, 2); max(*args, **{})')
- check_snippet('abs(val=0)')
+ if isinstance(seen[0], Method):
+ found = 'method %s of %s' % (
+ seen[0].w_function.name,
+ seen[0].w_class.getname(space, '?'))
+ else:
+ assert isinstance(seen[0], Function)
+ found = 'builtin %s' % seen[0].name
+ assert found == expected_c_call
+
+ check_snippet('l = []; l.append(42)', 'method append of list')
+ check_snippet('max(1, 2)', 'builtin max')
+ check_snippet('args = (1, 2); max(*args)', 'builtin max')
+ check_snippet('max(1, 2, **{})', 'builtin max')
+ check_snippet('args = (1, 2); max(*args, **{})', 'builtin max')
+ check_snippet('abs(val=0)', 'builtin abs')
def test_llprofile_c_exception(self):
l = []
@@ -243,6 +261,13 @@
""")
+class TestExecutionContextWithCallLikelyBuiltin(TestExecutionContext):
+ keywords = {'objspace.opcodes.CALL_LIKELY_BUILTIN': True}
+
+class TestExecutionContextWithCallMethod(TestExecutionContext):
+ keywords = {'objspace.opcodes.CALL_METHOD': True}
+
+
class AppTestDelNotBlocked:
def setup_method(self, meth):
Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_function.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_function.py Sun Dec 12 18:11:19 2010
@@ -6,7 +6,7 @@
from pypy.interpreter.argument import Arguments
-class AppTestFunctionIntrospection:
+class AppTestFunctionIntrospection:
def test_attributes(self):
globals()['__name__'] = 'mymodulename'
def f(): pass
@@ -90,10 +90,10 @@
def f(*args):
return 42
raises(TypeError, "dir.func_code = f.func_code")
- raises(TypeError, "list.append.im_func.func_code = f.func_code")
+ raises(TypeError, "list.append.im_func.func_code = f.func_code")
-class AppTestFunction:
+class AppTestFunction:
def test_simple_call(self):
def func(arg1, arg2):
return arg1, arg2
@@ -118,7 +118,7 @@
assert res[2] == 333
raises(TypeError, func)
- raises(TypeError, func, 1, 2, 3, 4)
+ raises(TypeError, func, 1, 2, 3, 4)
def test_simple_varargs(self):
def func(arg1, *args):
@@ -129,7 +129,7 @@
res = func(23, *(42,))
assert res[0] == 23
- assert res[1] == (42,)
+ assert res[1] == (42,)
def test_simple_kwargs(self):
def func(arg1, **kwargs):
@@ -222,7 +222,7 @@
func(**{'self': 23})
assert False
except TypeError:
- pass
+ pass
def test_kwargs_confusing_name(self):
def func(self): # 'self' conflicts with the interp-level
@@ -304,7 +304,7 @@
# on function types
raises(ValueError, type(f).__setstate__, f, (1, 2, 3))
-class AppTestMethod:
+class AppTestMethod:
def test_simple_call(self):
class A(object):
def func(self, arg2):
@@ -325,7 +325,7 @@
res = a.func(*(42,))
assert res[0] is a
- assert res[1] == (42,)
+ assert res[1] == (42,)
def test_obscure_varargs(self):
class A(object):
@@ -338,14 +338,14 @@
res = a.func(*(42,))
assert res[0] is a
- assert res[1] == 42
+ assert res[1] == 42
def test_simple_kwargs(self):
class A(object):
def func(self, **kwargs):
return self, kwargs
a = A()
-
+
res = a.func(value=42)
assert res[0] is a
assert res[1] == {'value': 42}
@@ -399,19 +399,19 @@
assert hash(C.m) == hash(D.m)
assert hash(c.m) == hash(c.m)
- def test_method_repr(self):
- class A(object):
- def f(self):
+ def test_method_repr(self):
+ class A(object):
+ def f(self):
pass
assert repr(A.f) == "<unbound method A.f>"
- assert repr(A().f).startswith("<bound method A.f of <")
- assert repr(A().f).endswith(">>")
+ assert repr(A().f).startswith("<bound method A.f of <")
+ assert repr(A().f).endswith(">>")
class B:
def f(self):
pass
assert repr(B.f) == "<unbound method B.f>"
assert repr(B().f).startswith("<bound method B.f of <")
- assert repr(A().f).endswith(">>")
+ assert repr(A().f).endswith(">>")
def test_method_call(self):
@@ -504,14 +504,33 @@
def f(): pass
raises(TypeError, new.instancemethod, f, None)
+ def test_empty_arg_kwarg_call(self):
+ def f():
+ pass
+
+ raises(TypeError, lambda: f(*0))
+ raises(TypeError, lambda: f(**0))
+
+ def test_method_equal(self):
+ class A(object):
+ def m(self):
+ pass
+
+ class X(object):
+ def __eq__(self, other):
+ return True
-class TestMethod:
+ assert A().m == X()
+ assert X() == A().m
+
+
+class TestMethod:
def setup_method(self, method):
def c(self, bar):
return bar
code = PyCode._from_code(self.space, c.func_code)
self.fn = Function(self.space, code, self.space.newdict())
-
+
def test_get(self):
space = self.space
w_meth = descr_function_get(space, self.fn, space.wrap(5), space.type(space.wrap(5)))
@@ -569,7 +588,7 @@
def test_call_function(self):
space = self.space
-
+
d = {}
for i in range(10):
args = "(" + ''.join(["a%d," % a for a in range(i)]) + ")"
@@ -591,14 +610,14 @@
code.funcrun = bomb
code.funcrun_obj = bomb
- args_w = map(space.wrap, range(i))
+ args_w = map(space.wrap, range(i))
w_res = space.call_function(fn, *args_w)
check = space.is_true(space.eq(w_res, space.wrap(res)))
assert check
def test_flatcall(self):
space = self.space
-
+
def f(a):
return a
code = PyCode._from_code(self.space, f.func_code)
@@ -625,7 +644,7 @@
def test_flatcall_method(self):
space = self.space
-
+
def f(self, a):
return a
code = PyCode._from_code(self.space, f.func_code)
@@ -653,7 +672,7 @@
def test_flatcall_default_arg(self):
space = self.space
-
+
def f(a, b):
return a+b
code = PyCode._from_code(self.space, f.func_code)
@@ -682,7 +701,7 @@
def test_flatcall_default_arg_method(self):
space = self.space
-
+
def f(self, a, b):
return a+b
code = PyCode._from_code(self.space, f.func_code)
@@ -705,7 +724,7 @@
y = A().m(x)
b = A().m
z = b(x)
- return y+10*z
+ return y+10*z
""")
assert space.eq_w(w_res, space.wrap(44))
Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py Sun Dec 12 18:11:19 2010
@@ -17,7 +17,6 @@
from pypy.jit.backend.llsupport.descr import get_call_descr
from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr
from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr
-from pypy.jit.backend.llsupport.ffisupport import get_call_descr_dynamic
from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -247,7 +246,9 @@
return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo=None):
- return get_call_descr_dynamic(ffi_args, ffi_result, extrainfo)
+ from pypy.jit.backend.llsupport import ffisupport
+ return ffisupport.get_call_descr_dynamic(ffi_args, ffi_result,
+ extrainfo)
def get_overflow_error(self):
ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/compile.py Sun Dec 12 18:11:19 2010
@@ -73,6 +73,8 @@
op.setdescr(None) # clear reference, mostly for tests
# mostly for tests: make sure we don't keep a reference to the LoopToken
loop.token = None
+ if not we_are_translated():
+ loop._number = looptoken.number
# ____________________________________________________________
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/graphpage.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/graphpage.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/graphpage.py Sun Dec 12 18:11:19 2010
@@ -31,8 +31,10 @@
def compute(self, graphs, errmsg=None):
resopgen = ResOpGen()
for graph, highlight in graphs:
- if hasattr(graph, 'token'):
+ if getattr(graph, 'token', None) is not None:
resopgen.jumps_to_graphs[graph.token] = graph
+ if getattr(graph, '_number', None) is not None:
+ resopgen.jumps_to_graphs[graph._number] = graph
for graph, highlight in graphs:
resopgen.add_graph(graph, highlight)
@@ -173,7 +175,10 @@
if tgt is None:
tgt_g = graphindex
else:
- tgt = self.jumps_to_graphs.get(tgt)
+ if tgt in self.jumps_to_graphs:
+ tgt = self.jumps_to_graphs[tgt]
+ else:
+ tgt = self.jumps_to_graphs.get(tgt.number)
if tgt is not None:
tgt_g = self.graphs.index(tgt)
if tgt_g != -1:
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py Sun Dec 12 18:11:19 2010
@@ -3,7 +3,6 @@
from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
from pypy.jit.metainterp.optimizeopt.heap import OptHeap
-from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
from pypy.jit.metainterp.optimizeopt.string import OptString
def optimize_loop_1(metainterp_sd, loop, virtuals=True):
@@ -17,6 +16,10 @@
OptVirtualize(),
OptString(),
OptHeap(),
+ ]
+ if metainterp_sd.jit_ffi:
+ from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
+ optimizations = optimizations + [
OptFfiCall(),
]
optimizer = Optimizer(metainterp_sd, loop, optimizations, virtuals)
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py Sun Dec 12 18:11:19 2010
@@ -1216,7 +1216,8 @@
logger_ops = None
def __init__(self, cpu, options,
- ProfilerClass=EmptyProfiler, warmrunnerdesc=None):
+ ProfilerClass=EmptyProfiler, warmrunnerdesc=None,
+ jit_ffi=True):
self.cpu = cpu
self.stats = self.cpu.stats
self.options = options
@@ -1226,6 +1227,7 @@
self.profiler = ProfilerClass()
self.profiler.cpu = cpu
self.warmrunnerdesc = warmrunnerdesc
+ self.jit_ffi = jit_ffi
backendmodule = self.cpu.__module__
backendmodule = backendmodule.split('.')[-2]
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py Sun Dec 12 18:11:19 2010
@@ -54,6 +54,7 @@
stats = Stats()
profiler = jitprof.EmptyProfiler()
warmrunnerdesc = None
+ jit_ffi = False
def log(self, msg, event_kind=None):
pass
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_fficall.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_fficall.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_fficall.py Sun Dec 12 18:11:19 2010
@@ -40,6 +40,6 @@
n += 1
return res
#
- res = self.meta_interp(f, [0])
+ res = self.meta_interp(f, [0], jit_ffi=True)
return res
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefficall.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefficall.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefficall.py Sun Dec 12 18:11:19 2010
@@ -31,6 +31,7 @@
class TestFfiCall(BaseTestOptimizeOpt, LLtypeMixin):
+ jit_ffi = True
class namespace:
cpu = LLtypeMixin.cpu
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py Sun Dec 12 18:11:19 2010
@@ -28,11 +28,12 @@
class FakeMetaInterpStaticData(object):
- def __init__(self, cpu):
+ def __init__(self, cpu, jit_ffi=False):
self.cpu = cpu
self.profiler = EmptyProfiler()
self.options = Fake()
self.globaldata = Fake()
+ self.jit_ffi = jit_ffi
def test_store_final_boxes_in_guard():
from pypy.jit.metainterp.compile import ResumeGuardDescr
@@ -227,6 +228,7 @@
return sorted(boxes, key=lambda box: _kind2count[box.type])
class BaseTestOptimizeOpt(BaseTest):
+ jit_ffi = False
def invent_fail_descr(self, fail_args):
if fail_args is None:
@@ -261,7 +263,7 @@
loop.token.specnodes = self.unpack_specnodes(spectext)
#
self.loop = loop
- metainterp_sd = FakeMetaInterpStaticData(self.cpu)
+ metainterp_sd = FakeMetaInterpStaticData(self.cpu, self.jit_ffi)
if hasattr(self, 'vrefinfo'):
metainterp_sd.virtualref_info = self.vrefinfo
if hasattr(self, 'callinfocollection'):
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py Sun Dec 12 18:11:19 2010
@@ -144,7 +144,8 @@
class WarmRunnerDesc(object):
def __init__(self, translator, policy=None, backendopt=True, CPUClass=None,
- optimizer=None, ProfilerClass=EmptyProfiler, **kwds):
+ optimizer=None, ProfilerClass=EmptyProfiler,
+ jit_ffi=None, **kwds):
pyjitpl._warmrunnerdesc = self # this is a global for debugging only!
self.set_translator(translator)
self.memory_manager = memmgr.MemoryManager()
@@ -162,7 +163,7 @@
elif self.opt.listops:
self.prejit_optimizations_minimal_inline(policy, graphs)
- self.build_meta_interp(ProfilerClass)
+ self.build_meta_interp(ProfilerClass, jit_ffi)
self.make_args_specifications()
#
from pypy.jit.metainterp.virtualref import VirtualRefInfo
@@ -280,11 +281,14 @@
translate_support_code, gcdescr=self.gcdescr)
self.cpu = cpu
- def build_meta_interp(self, ProfilerClass):
+ def build_meta_interp(self, ProfilerClass, jit_ffi=None):
+ if jit_ffi is None:
+ jit_ffi = self.translator.config.translation.jit_ffi
self.metainterp_sd = MetaInterpStaticData(self.cpu,
self.opt,
ProfilerClass=ProfilerClass,
- warmrunnerdesc=self)
+ warmrunnerdesc=self,
+ jit_ffi=jit_ffi)
def make_virtualizable_infos(self):
vinfos = {}
Modified: pypy/branch/fast-forward/pypy/module/_lsprof/interp_lsprof.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_lsprof/interp_lsprof.py (original)
+++ pypy/branch/fast-forward/pypy/module/_lsprof/interp_lsprof.py Sun Dec 12 18:11:19 2010
@@ -164,8 +164,11 @@
if isinstance(w_arg, Method):
w_function = w_arg.w_function
class_name = w_arg.w_class.getname(space, '?')
- assert isinstance(w_function, Function)
- return "{method '%s' of '%s' objects}" % (w_function.name, class_name)
+ if isinstance(w_function, Function):
+ name = w_function.name
+ else:
+ name = '?'
+ return "{method '%s' of '%s' objects}" % (name, class_name)
elif isinstance(w_arg, Function):
if w_arg.w_module is None:
module = ''
@@ -177,7 +180,8 @@
module += '.'
return '{%s%s}' % (module, w_arg.name)
else:
- return '{!!!unknown!!!}'
+ class_name = space.type(w_arg).getname(space, '?')
+ return "{'%s' object}" % (class_name,)
def lsprof_call(space, w_self, frame, event, w_arg):
assert isinstance(w_self, W_Profiler)
Modified: pypy/branch/fast-forward/pypy/module/_lsprof/test/test_cprofile.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_lsprof/test/test_cprofile.py (original)
+++ pypy/branch/fast-forward/pypy/module/_lsprof/test/test_cprofile.py Sun Dec 12 18:11:19 2010
@@ -2,9 +2,10 @@
from pypy.conftest import gettestobjspace, option
class AppTestCProfile(object):
+ keywords = {}
def setup_class(cls):
- space = gettestobjspace(usemodules=('_lsprof',))
+ space = gettestobjspace(usemodules=('_lsprof',), **cls.keywords)
cls.w_expected_output = space.wrap(expected_output)
cls.space = space
cls.w_file = space.wrap(__file__)
@@ -148,6 +149,12 @@
finally:
sys.path.pop(0)
+
+class AppTestWithDifferentBytecodes(AppTestCProfile):
+ keywords = {'objspace.opcodes.CALL_LIKELY_BUILTIN': True,
+ 'objspace.opcodes.CALL_METHOD': True}
+
+
expected_output = {}
expected_output['print_stats'] = """\
126 function calls (106 primitive calls) in 1.000 CPU seconds
@@ -165,11 +172,11 @@
2 0.000 0.000 0.140 0.070 profilee.py:84(helper2_indirect)
8 0.312 0.039 0.400 0.050 profilee.py:88(helper2)
8 0.064 0.008 0.080 0.010 profilee.py:98(subhelper)
- 4 0.000 0.000 0.000 0.000 {.*append.*}
+ 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {.*disable.*}
- 12 0.000 0.000 0.012 0.001 {hasattr.*}
- 8 0.000 0.000 0.000 0.000 {range.*}
- 4 0.000 0.000 0.000 0.000 {sys.exc_info.*}
+ 12 0.000 0.000 0.012 0.001 {hasattr}
+ 8 0.000 0.000 0.000 0.000 {range}
+ 4 0.000 0.000 0.000 0.000 {sys.exc_info}
"""
Modified: pypy/branch/fast-forward/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/__init__.py Sun Dec 12 18:11:19 2010
@@ -47,6 +47,7 @@
import pypy.module.cpyext.weakrefobject
import pypy.module.cpyext.funcobject
import pypy.module.cpyext.classobject
+import pypy.module.cpyext.pypyintf
import pypy.module.cpyext.memoryobject
import pypy.module.cpyext.codecs
Modified: pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c (original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c Sun Dec 12 18:11:19 2010
@@ -459,6 +459,7 @@
bufsize);
return msgbuf;
}
+ PyPy_Borrow(arg, item);
msg = convertitem(item, &format, p_va, flags, levels+1,
msgbuf, bufsize, freelist);
if (msg != NULL) {
Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original)
+++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Sun Dec 12 18:11:19 2010
@@ -505,6 +505,7 @@
self.w_text = space.w_None
self.w_msg = space.w_None
self.w_print_file_and_line = space.w_None # what's that?
+ self.w_lastlineno = space.w_None # this is a pypy extension
W_BaseException.__init__(self, space)
def descr_init(self, space, args_w):
@@ -512,11 +513,16 @@
if len(args_w) > 0:
self.w_msg = args_w[0]
if len(args_w) == 2:
- values_w = space.fixedview(args_w[1], 4)
- self.w_filename = values_w[0]
- self.w_lineno = values_w[1]
- self.w_offset = values_w[2]
- self.w_text = values_w[3]
+ values_w = space.fixedview(args_w[1])
+ if len(values_w) > 0: self.w_filename = values_w[0]
+ if len(values_w) > 1: self.w_lineno = values_w[1]
+ if len(values_w) > 2: self.w_offset = values_w[2]
+ if len(values_w) > 3: self.w_text = values_w[3]
+ if len(values_w) > 4:
+ self.w_lastlineno = values_w[4] # PyPy extension
+ # kill the extra items from args_w to prevent undesired effects
+ args_w = args_w[:]
+ args_w[1] = space.newtuple(values_w[:4])
W_BaseException.descr_init(self, space, args_w)
descr_init.unwrap_spec = ['self', ObjSpace, 'args_w']
@@ -525,29 +531,52 @@
if type(self.msg) is not str:
return str(self.msg)
+ lineno = None
buffer = self.msg
have_filename = type(self.filename) is str
- have_lineno = type(self.lineno) is int
+ if type(self.lineno) is int:
+ if (type(self.lastlineno) is int and
+ self.lastlineno > self.lineno):
+ lineno = 'lines %d-%d' % (self.lineno, self.lastlineno)
+ else:
+ lineno = 'line %d' % (self.lineno,)
if have_filename:
import os
fname = os.path.basename(self.filename or "???")
- if have_lineno:
- buffer = "%s (%s, line %ld)" % (self.msg, fname, self.lineno)
+ if lineno:
+ buffer = "%s (%s, %s)" % (self.msg, fname, lineno)
else:
buffer ="%s (%s)" % (self.msg, fname)
- elif have_lineno:
- buffer = "%s (line %ld)" % (self.msg, self.lineno)
+ elif lineno:
+ buffer = "%s (%s)" % (self.msg, lineno)
return buffer
""")
descr_str.unwrap_spec = ['self', ObjSpace]
+ def descr_repr(self, space):
+ if (len(self.args_w) == 2
+ and not space.is_w(self.w_lastlineno, space.w_None)
+ and space.int_w(space.len(self.args_w[1])) == 4):
+ # fake a 5-element tuple in the repr, suitable for calling
+ # __init__ again
+ values_w = space.fixedview(self.args_w[1])
+ w_tuple = space.newtuple(values_w + [self.w_lastlineno])
+ args_w = [self.args_w[0], w_tuple]
+ args_repr = space.str_w(space.repr(space.newtuple(args_w)))
+ clsname = self.getclass(space).getname(space, '?')
+ return space.wrap(clsname + args_repr)
+ else:
+ return W_StandardError.descr_repr(self, space)
+ descr_repr.unwrap_spec = ['self', ObjSpace]
+
W_SyntaxError.typedef = TypeDef(
'SyntaxError',
W_StandardError.typedef,
__new__ = _new(W_SyntaxError),
__init__ = interp2app(W_SyntaxError.descr_init),
__str__ = interp2app(W_SyntaxError.descr_str),
+ __repr__ = interp2app(W_SyntaxError.descr_repr),
__doc__ = W_SyntaxError.__doc__,
__module__ = 'exceptions',
msg = readwrite_attrproperty_w('w_msg', W_SyntaxError),
@@ -557,6 +586,7 @@
text = readwrite_attrproperty_w('w_text', W_SyntaxError),
print_file_and_line = readwrite_attrproperty_w('w_print_file_and_line',
W_SyntaxError),
+ lastlineno = readwrite_attrproperty_w('w_lastlineno', W_SyntaxError),
)
W_FutureWarning = _new_exception('FutureWarning', W_Warning,
Modified: pypy/branch/fast-forward/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/imp/importing.py (original)
+++ pypy/branch/fast-forward/pypy/module/imp/importing.py Sun Dec 12 18:11:19 2010
@@ -564,7 +564,7 @@
space.sys.setmodule(w_module)
raise
finally:
- space.reloading_modules.clear()
+ del space.reloading_modules[modulename]
# __________________________________________________________________
Modified: pypy/branch/fast-forward/pypy/module/posix/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/__init__.py Sun Dec 12 18:11:19 2010
@@ -77,6 +77,8 @@
interpleveldefs['fsync'] = 'interp_posix.fsync'
if hasattr(os, 'fdatasync'):
interpleveldefs['fdatasync'] = 'interp_posix.fdatasync'
+ if hasattr(os, 'fchdir'):
+ interpleveldefs['fchdir'] = 'interp_posix.fchdir'
if hasattr(os, 'putenv'):
interpleveldefs['putenv'] = 'interp_posix.putenv'
if hasattr(posix, 'unsetenv'): # note: emulated in os
@@ -113,6 +115,8 @@
interpleveldefs['sysconf_names'] = 'space.wrap(os.sysconf_names)'
if hasattr(os, 'ttyname'):
interpleveldefs['ttyname'] = 'interp_posix.ttyname'
+ if hasattr(os, 'getloadavg'):
+ interpleveldefs['getloadavg'] = 'interp_posix.getloadavg'
for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
'seteuid', 'setgid', 'setegid', 'getpgrp', 'setpgrp',
Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Sun Dec 12 18:11:19 2010
@@ -4,6 +4,7 @@
from pypy.rlib.rarithmetic import r_longlong
from pypy.rlib.unroll import unrolling_iterable
from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2
+from pypy.interpreter.error import operationerrfmt
from pypy.rpython.module.ll_os import RegisterOs
from pypy.rpython.module import ll_os_stat
from pypy.rpython.lltypesystem import rffi, lltype
@@ -159,19 +160,29 @@
raise wrap_oserror(space, e)
ftruncate.unwrap_spec = [ObjSpace, "c_int", r_longlong]
-def fsync(space, fd):
+def fsync(space, w_fd):
+ fd = space.c_filedescriptor_w(w_fd)
try:
os.fsync(fd)
except OSError, e:
raise wrap_oserror(space, e)
-fsync.unwrap_spec = [ObjSpace, "c_int"]
+fsync.unwrap_spec = [ObjSpace, W_Root]
-def fdatasync(space, fd):
+def fdatasync(space, w_fd):
+ fd = space.c_filedescriptor_w(w_fd)
try:
os.fdatasync(fd)
except OSError, e:
raise wrap_oserror(space, e)
-fdatasync.unwrap_spec = [ObjSpace, "c_int"]
+fdatasync.unwrap_spec = [ObjSpace, W_Root]
+
+def fchdir(space, w_fd):
+ fd = space.c_filedescriptor_w(w_fd)
+ try:
+ os.fchdir(fd)
+ except OSError, e:
+ raise wrap_oserror(space, e)
+fchdir.unwrap_spec = [ObjSpace, W_Root]
# ____________________________________________________________
@@ -1023,6 +1034,17 @@
return space.w_None
chown.unwrap_spec = [ObjSpace, str, "c_nonnegint", "c_nonnegint"]
+def getloadavg(space):
+ try:
+ load = os.getloadavg()
+ except OSError, e:
+ raise OperationError(space.w_OSError,
+ space.wrap("Load averages are unobtainable"))
+ return space.newtuple([space.wrap(load[0]),
+ space.wrap(load[1]),
+ space.wrap(load[2])])
+getloadavg.unwrap_spec = [ObjSpace]
+
if _WIN:
from pypy.rlib import rwin32
Modified: pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Sun Dec 12 18:11:19 2010
@@ -534,6 +534,14 @@
assert os.WIFEXITED(status)
assert os.WEXITSTATUS(status) == exit_status
+ if hasattr(os, 'getloadavg'):
+ def test_os_getloadavg(self):
+ os = self.posix
+ l0, l1, l2 = os.getloadavg()
+ assert type(l0) is float and l0 >= 0.0
+ assert type(l1) is float and l0 >= 0.0
+ assert type(l2) is float and l0 >= 0.0
+
if hasattr(os, 'fsync'):
def test_fsync(self):
os = self.posix
@@ -541,30 +549,42 @@
try:
fd = f.fileno()
os.fsync(fd)
- finally:
+ os.fsync(long(fd))
+ os.fsync(f) # <- should also work with a file, or anything
+ finally: # with a fileno() method
f.close()
- try:
- os.fsync(fd)
- except OSError:
- pass
- else:
- raise AssertionError("os.fsync didn't raise")
+ raises(OSError, os.fsync, fd)
+ raises(ValueError, os.fsync, -1)
if hasattr(os, 'fdatasync'):
def test_fdatasync(self):
os = self.posix
- f = open(self.path2)
+ f = open(self.path2, "w")
try:
fd = f.fileno()
os.fdatasync(fd)
finally:
f.close()
+ raises(OSError, os.fdatasync, fd)
+ raises(ValueError, os.fdatasync, -1)
+
+ if hasattr(os, 'fchdir'):
+ def test_fchdir(self):
+ os = self.posix
+ localdir = os.getcwd()
try:
- os.fdatasync(fd)
- except OSError:
- pass
- else:
- raise AssertionError("os.fdatasync didn't raise")
+ os.mkdir(self.path2 + 'dir')
+ fd = os.open(self.path2 + 'dir', os.O_RDONLY)
+ try:
+ os.fchdir(fd)
+ mypath = os.getcwd()
+ finally:
+ os.close(fd)
+ assert mypath.endswith('test_posix2-dir')
+ raises(OSError, os.fchdir, fd)
+ raises(ValueError, os.fchdir, -1)
+ finally:
+ os.chdir(localdir)
def test_largefile(self):
os = self.posix
Modified: pypy/branch/fast-forward/pypy/module/select/interp_select.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/select/interp_select.py (original)
+++ pypy/branch/fast-forward/pypy/module/select/interp_select.py Sun Dec 12 18:11:19 2010
@@ -14,32 +14,12 @@
unregistering file descriptors, and then polling them for I/O events."""
return Poll()
-def as_fd_w(space, w_fd):
- if not space.is_true(space.isinstance(w_fd, space.w_int)):
- try:
- w_fileno = space.getattr(w_fd, space.wrap('fileno'))
- except OperationError, e:
- if e.match(space, space.w_AttributeError):
- raise OperationError(space.w_TypeError,
- space.wrap("argument must be an int, or have a fileno() method."))
- raise
- w_fd = space.call_function(w_fileno)
- if not space.is_true(space.isinstance(w_fd, space.w_int)):
- raise OperationError(space.w_TypeError,
- space.wrap('filneo() return a non-integer'))
-
- fd = space.int_w(w_fd)
- if fd < 0:
- raise operationerrfmt(space.w_ValueError,
- "file descriptor cannot be a negative integer (%d)", fd)
- return fd
-
class Poll(Wrappable):
def __init__(self):
self.fddict = {}
def register(self, space, w_fd, events=defaultevents):
- fd = as_fd_w(space, w_fd)
+ fd = space.c_filedescriptor_w(w_fd)
self.fddict[fd] = events
register.unwrap_spec = ['self', ObjSpace, W_Root, int]
@@ -52,7 +32,7 @@
modify.unwrap_spec = ['self', ObjSpace, W_Root, int]
def unregister(self, space, w_fd):
- fd = as_fd_w(space, w_fd)
+ fd = space.c_filedescriptor_w(w_fd)
try:
del self.fddict[fd]
except KeyError:
@@ -123,9 +103,9 @@
iwtd_w = space.listview(w_iwtd)
owtd_w = space.listview(w_owtd)
ewtd_w = space.listview(w_ewtd)
- iwtd = [as_fd_w(space, w_f) for w_f in iwtd_w]
- owtd = [as_fd_w(space, w_f) for w_f in owtd_w]
- ewtd = [as_fd_w(space, w_f) for w_f in ewtd_w]
+ iwtd = [space.c_filedescriptor_w(w_f) for w_f in iwtd_w]
+ owtd = [space.c_filedescriptor_w(w_f) for w_f in owtd_w]
+ ewtd = [space.c_filedescriptor_w(w_f) for w_f in ewtd_w]
iwtd_d = {}
owtd_d = {}
ewtd_d = {}
Modified: pypy/branch/fast-forward/pypy/module/sys/vm.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/vm.py (original)
+++ pypy/branch/fast-forward/pypy/module/sys/vm.py Sun Dec 12 18:11:19 2010
@@ -51,7 +51,7 @@
space.wrap("recursion limit must be positive"))
# global recursion_limit
# we need to do it without writing globals.
- space.warn('setrecursionlimit deprecated', space.w_DeprecationWarning)
+ space.warn('setrecursionlimit() is ignored (and not needed) on PyPy', space.w_DeprecationWarning)
space.sys.recursionlimit = new_limit
def getrecursionlimit(space):
Modified: pypy/branch/fast-forward/pypy/module/test_lib_pypy/ctypes_tests/test_cast.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/test_lib_pypy/ctypes_tests/test_cast.py (original)
+++ pypy/branch/fast-forward/pypy/module/test_lib_pypy/ctypes_tests/test_cast.py Sun Dec 12 18:11:19 2010
@@ -82,8 +82,11 @@
def test_cast_functype(self):
# make sure we can cast function type
my_sqrt = lib.my_sqrt
+ saved_objects = my_sqrt._objects.copy()
sqrt = cast(cast(my_sqrt, c_void_p), CFUNCTYPE(c_double, c_double))
assert sqrt(4.0) == 2.0
assert not cast(0, CFUNCTYPE(c_int))
-
-
+ #
+ assert sqrt._objects is my_sqrt._objects # on CPython too
+ my_sqrt._objects.clear()
+ my_sqrt._objects.update(saved_objects)
Modified: pypy/branch/fast-forward/pypy/objspace/std/complexobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/complexobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/complexobject.py Sun Dec 12 18:11:19 2010
@@ -25,90 +25,92 @@
""" representation for debugging purposes """
return "<W_ComplexObject(%f,%f)>" % (w_self.realval, w_self.imagval)
-registerimplementation(W_ComplexObject)
-
-c_1 = (1.0, 0.0)
+ def sub(self, other):
+ return W_ComplexObject(self.realval - other.realval,
+ self.imagval - other.imagval)
+
+ def mul(self, other):
+ r = self.realval * other.realval - self.imagval * other.imagval
+ i = self.realval * other.imagval + self.imagval * other.realval
+ return W_ComplexObject(r, i)
+
+ def div(self, other):
+ r1, i1 = self.realval, self.imagval
+ r2, i2 = other.realval, other.imagval
+ if r2 < 0:
+ abs_r2 = - r2
+ else:
+ abs_r2 = r2
+ if i2 < 0:
+ abs_i2 = - i2
+ else:
+ abs_i2 = i2
+ if abs_r2 >= abs_i2:
+ if abs_r2 == 0.0:
+ raise ZeroDivisionError
+ else:
+ ratio = i2 / r2
+ denom = r2 + i2 * ratio
+ rr = (r1 + i1 * ratio) / denom
+ ir = (i1 - r1 * ratio) / denom
+ else:
+ ratio = r2 / i2
+ denom = r2 * ratio + i2
+ assert i2 != 0.0
+ rr = (r1 * ratio + i1) / denom
+ ir = (i1 * ratio - r1) / denom
+ return W_ComplexObject(rr,ir)
+
+ def divmod(self, other):
+ w_div = self.div(other)
+ div = math.floor(w_div.realval)
+ w_mod = self.sub(
+ W_ComplexObject(other.realval * div, other.imagval * div))
+ return (W_ComplexObject(div, 0), w_mod)
+
+ def pow(self, other):
+ r1, i1 = self.realval, self.imagval
+ r2, i2 = other.realval, other.imagval
+ if r2 == 0.0 and i2 == 0.0:
+ rr, ir = 1, 0
+ elif r1 == 0.0 and i1 == 0.0:
+ if i2 != 0.0 or r2 < 0.0:
+ raise ZeroDivisionError
+ rr, ir = (0.0, 0.0)
+ else:
+ vabs = math.hypot(r1,i1)
+ len = math.pow(vabs,r2)
+ at = math.atan2(i1,r1)
+ phase = at * r2
+ if i2 != 0.0:
+ len /= math.exp(at * i2)
+ phase += i2 * math.log(vabs)
+ rr = len * math.cos(phase)
+ ir = len * math.sin(phase)
+ return W_ComplexObject(rr, ir)
+
+ def pow_int(self, n):
+ if n > 100 or n < -100:
+ return self.pow(W_ComplexObject(1.0 * n, 0.0))
+ elif n > 0:
+ return self.pow_positive_int(n)
+ else:
+ return w_one.div(self.pow_positive_int(-n))
-def _sum(c1, c2):
- return (c1[0]+c2[0],c1[1]+c2[1])
+ def pow_positive_int(self, n):
+ mask = 1
+ w_result = w_one
+ while mask > 0 and n >= mask:
+ if n & mask:
+ w_result = w_result.mul(self)
+ mask <<= 1
+ self = self.mul(self)
-def _diff(c1, c2):
- return (c1[0]-c2[0],c1[1]-c2[1])
+ return w_result
-def _prod(c1, c2):
- r = c1[0]*c2[0] - c1[1]*c2[1]
- i = c1[0]*c2[1] + c1[1]*c2[0]
- return (r,i)
-
-def _quot(c1,c2):
- r1, i1 = c1
- r2, i2 = c2
- if r2 < 0:
- abs_r2 = - r2
- else:
- abs_r2 = r2
- if i2 < 0:
- abs_i2 = - i2
- else:
- abs_i2 = i2
- if abs_r2 >= abs_i2:
- if abs_r2 == 0.0:
- raise ZeroDivisionError
- else:
- ratio = i2 / r2
- denom = r2 + i2 * ratio
- rr = (r1 + i1 * ratio) / denom
- ir = (i1 - r1 * ratio) / denom
- else:
- ratio = r2 / i2
- denom = r2 * ratio + i2
- assert i2 != 0.0
- rr = (r1 * ratio + i1) / denom
- ir = (i1 * ratio - r1) / denom
- return (rr,ir)
-
-def _pow(c1,c2):
- r1, i1 = c1
- r2, i2 = c2
- if r2 == 0.0 and i2 == 0.0:
- rr, ir = c_1
- elif r1 == 0.0 and i1 == 0.0:
- if i2 != 0.0 or r2 < 0.0:
- raise ZeroDivisionError
- rr, ir = (0.0, 0.0)
- else:
- vabs = math.hypot(r1,i1)
- len = math.pow(vabs,r2)
- at = math.atan2(i1,r1)
- phase = at * r2
- if i2 != 0.0:
- len /= math.exp(at * i2)
- phase += i2 * math.log(vabs)
- rr = len * math.cos(phase)
- ir = len * math.sin(phase)
- return (rr, ir)
-
-def _powu(c,n):
- mask = 1;
- rr, ir = c_1
- rp = c[0]
- ip = c[1]
- while mask > 0 and n >= mask:
- if n & mask:
- rr, ir = _prod((rr, ir), (rp, ip))
- mask <<= 1
- rp, ip = _prod((rp, ip), (rp, ip))
-
- return (rr, ir)
-
-def _powi(c,n):
- if n > 100 or n < -100:
- return _pow(c,(1.0 * n, 0.0))
- elif n > 0:
- return _powu(c, n)
- else:
- return _quot(c_1, _powu(c, -n))
+registerimplementation(W_ComplexObject)
+w_one = W_ComplexObject(1, 0)
def delegate_Bool2Complex(space, w_bool):
@@ -128,38 +130,25 @@
return W_ComplexObject(w_float.floatval, 0.0)
def hash__Complex(space, w_value):
- #this is straight out of CPython complex implementation
-
hashreal = _hash_float(space, w_value.realval)
- if hashreal == -1:
- return space.newint(-1)
hashimg = _hash_float(space, w_value.imagval)
- if hashimg == -1:
- return space.newint(-1)
combined = hashreal + 1000003 * hashimg
- if (combined == -1):
- combined = -2
return space.newint(combined)
-def _w2t(space, w_complex):
- "convert an interplevel complex object to a tuple representation"
- return w_complex.realval, w_complex.imagval
-
-def _t2w(space, c):
- return W_ComplexObject(c[0], c[1])
-
def add__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _sum(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return W_ComplexObject(w_complex1.realval + w_complex2.realval,
+ w_complex1.imagval + w_complex2.imagval)
def sub__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _diff(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return W_ComplexObject(w_complex1.realval - w_complex2.realval,
+ w_complex1.imagval - w_complex2.imagval)
def mul__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _prod(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return w_complex1.mul(w_complex2)
def div__Complex_Complex(space, w_complex1, w_complex2):
try:
- return _t2w(space, _quot(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return w_complex1.div(w_complex2)
except ZeroDivisionError, e:
raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
@@ -167,49 +156,38 @@
def mod__Complex_Complex(space, w_complex1, w_complex2):
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ return w_complex1.divmod(w_complex2)[1]
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex remainder"))
- div = (math.floor(div[0]), 0.0)
- mod = _diff(_w2t(space, w_complex1), _prod(_w2t(space, w_complex2), div))
-
- return _t2w(space, mod)
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
def divmod__Complex_Complex(space, w_complex1, w_complex2):
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ div, mod = w_complex1.divmod(w_complex2)
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex divmod()"))
- div = (math.floor(div[0]), 0.0)
- mod = _diff(_w2t(space, w_complex1), _prod(_w2t(space, w_complex2), div))
- w_div = _t2w(space, div)
- w_mod = _t2w(space, mod)
- return space.newtuple([w_div, w_mod])
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
+ return space.newtuple([div, mod])
def floordiv__Complex_Complex(space, w_complex1, w_complex2):
+ # don't care about the slight slowdown you get from using divmod
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ return w_complex1.divmod(w_complex2)[0]
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex floordiv()"))
- div = (math.floor(div[0]), 0.0)
- return _t2w(space, div)
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
-def pow__Complex_Complex_ANY(space, w_complex1, w_complex2, thirdArg):
+def pow__Complex_Complex_ANY(space, w_complex, w_exponent, thirdArg):
if not space.is_w(thirdArg, space.w_None):
raise OperationError(space.w_ValueError, space.wrap('complex modulo'))
+ int_exponent = int(w_exponent.realval)
try:
- v = _w2t(space, w_complex1)
- exponent = _w2t(space, w_complex2)
- int_exponent = int(exponent[0])
- if exponent[1] == 0.0 and exponent[0] == int_exponent:
- p = _powi(v, int_exponent)
+ if w_exponent.imagval == 0.0 and w_exponent.realval == int_exponent:
+ w_p = w_complex.pow_int(int_exponent)
else:
- p = _pow(v, exponent)
+ w_p = w_complex.pow(w_exponent)
except ZeroDivisionError:
raise OperationError(space.w_ZeroDivisionError, space.wrap("0.0 to a negative or complex power"))
except OverflowError:
raise OperationError(space.w_OverflowError, space.wrap("complex exponentiation"))
- return _t2w(space, p)
+ return w_p
def neg__Complex(space, w_complex):
return W_ComplexObject(-w_complex.realval, -w_complex.imagval)
Modified: pypy/branch/fast-forward/pypy/objspace/std/complextype.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/complextype.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/complextype.py Sun Dec 12 18:11:19 2010
@@ -1,7 +1,7 @@
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError
from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.strutil import interp_string_to_float, ParseStringError
+from pypy.objspace.std.strutil import string_to_float, ParseStringError
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef
from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
@@ -135,8 +135,8 @@
except ValueError:
raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
try:
- realval = interp_string_to_float(space, realstr)
- imagval = interp_string_to_float(space, imagstr)
+ realval = string_to_float(realstr)
+ imagval = string_to_float(imagstr)
except ParseStringError:
raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
else:
Modified: pypy/branch/fast-forward/pypy/objspace/std/floattype.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/floattype.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/floattype.py Sun Dec 12 18:11:19 2010
@@ -8,7 +8,7 @@
from pypy.objspace.std.register_all import register_all
from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
from pypy.objspace.std.strutil import ParseStringError
-from pypy.objspace.std.strutil import interp_string_to_float
+from pypy.objspace.std.strutil import string_to_float
float_as_integer_ratio = SMM("as_integer_ratio", 1)
@@ -37,7 +37,7 @@
elif space.is_true(space.isinstance(w_value, space.w_str)):
strvalue = space.str_w(w_value)
try:
- value = interp_string_to_float(space, strvalue)
+ value = string_to_float(strvalue)
except ParseStringError, e:
raise OperationError(space.w_ValueError,
space.wrap(e.msg))
@@ -48,7 +48,7 @@
from unicodeobject import unicode_to_decimal_w
strvalue = unicode_to_decimal_w(space, w_value)
try:
- value = interp_string_to_float(space, strvalue)
+ value = string_to_float(strvalue)
except ParseStringError, e:
raise OperationError(space.w_ValueError,
space.wrap(e.msg))
Modified: pypy/branch/fast-forward/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/longobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/longobject.py Sun Dec 12 18:11:19 2010
@@ -45,19 +45,6 @@
fromrarith_int._annspecialcase_ = "specialize:argtype(0)"
fromrarith_int = staticmethod(fromrarith_int)
- def fromdecimalstr(s):
- return W_LongObject(rbigint.fromdecimalstr(s))
- fromdecimalstr = staticmethod(fromdecimalstr)
-
- def _count_bits(self):
- return self.num._count_bits()
-
- def is_odd(self):
- return self.num.is_odd()
-
- def get_sign(self):
- return self.num.sign
-
registerimplementation(W_LongObject)
# bool-to-long
Modified: pypy/branch/fast-forward/pypy/objspace/std/strutil.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/strutil.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/strutil.py Sun Dec 12 18:11:19 2010
@@ -156,7 +156,7 @@
del calc_mantissa_bits
MANTISSA_DIGITS = len(str( (1L << MANTISSA_BITS)-1 )) + 1
-def interp_string_to_float(space, s):
+def string_to_float(s):
"""
Conversion of string to float.
This version tries to only raise on invalid literals.
@@ -168,10 +168,9 @@
s = strip_spaces(s)
if not s:
- raise OperationError(space.w_ValueError, space.wrap(
- "empty string for float()"))
+ raise ParseStringError("empty string for float()")
+
-
low = s.lower()
if low == "-inf" or low == "-infinity":
return -INFINITY
@@ -212,68 +211,56 @@
if len(digits) == 0:
digits = '0'
- # a few abbreviations
- from pypy.objspace.std import longobject
- mklong = longobject.W_LongObject.fromint
- d2long = longobject.W_LongObject.fromdecimalstr
- adlong = longobject.add__Long_Long
- longup = longobject.pow__Long_Long_None
- multip = longobject.mul__Long_Long
- divide = longobject.div__Long_Long
- lshift = longobject.lshift__Long_Long
- rshift = longobject.rshift__Long_Long
-
# 4) compute the exponent and truncate to +-400
if not exponent:
exponent = '0'
- w_le = d2long(exponent)
- w_le = adlong(space, w_le, mklong(space, dexp))
+ long_exponent = rbigint.fromdecimalstr(exponent)
+ long_exponent = long_exponent.add(rbigint.fromint(dexp))
try:
- e = w_le.toint()
+ e = long_exponent.toint()
except OverflowError:
# XXX poking at internals
- e = w_le.num.sign * 400
- if e >= 400:
- e = 400
- elif e <= -400:
- e = -400
+ e = long_exponent.sign * 400
+ else:
+ if e >= 400:
+ e = 400
+ elif e <= -400:
+ e = -400
# 5) compute the value using long math and proper rounding.
- w_lr = d2long(digits)
- w_10 = mklong(space, 10)
- w_1 = mklong(space, 1)
+ b_digits = rbigint.fromdecimalstr(digits)
+ b_10 = rbigint.fromint(10)
+ b_1 = rbigint.fromint(1)
if e >= 0:
bits = 0
- w_pten = longup(space, w_10, mklong(space, e), space.w_None)
- w_m = multip(space, w_lr, w_pten)
+ b_power_of_ten = b_10.pow(rbigint.fromint(e))
+ b_mantissa = b_digits.mul(b_power_of_ten)
else:
# compute a sufficiently large scale
prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
- w_scale = lshift(space, w_1, mklong(space, -bits))
- w_pten = longup(space, w_10, mklong(space, -e), None)
- w_tmp = multip(space, w_lr, w_scale)
- w_m = divide(space, w_tmp, w_pten)
+ b_scale = b_1.lshift(-bits)
+ b_power_of_ten = b_10.pow(rbigint.fromint(-e))
+ b_mantissa = b_digits.mul(b_scale).div(b_power_of_ten)
# we now have a fairly large mantissa.
# Shift it and round the last bit.
# first estimate the bits and do a big shift
- mbits = w_m._count_bits()
+ mbits = b_mantissa._count_bits()
needed = MANTISSA_BITS
if mbits > needed:
if mbits > needed+1:
shifted = mbits - (needed+1)
- w_m = rshift(space, w_m, mklong(space, shifted))
+ b_mantissa = b_mantissa.rshift(shifted)
bits += shifted
# do the rounding
bits += 1
- round = w_m.is_odd()
- w_m = rshift(space, w_m, w_1)
- w_m = adlong(space, w_m, mklong(space, round))
+ round = b_mantissa.is_odd()
+ b_mantissa = b_mantissa.rshift(1).add(rbigint.fromint(round))
try:
- r = math.ldexp(w_m.tofloat(), bits)
+ r = math.ldexp(b_mantissa.tofloat(), bits)
# XXX I guess we do not check for overflow in ldexp as we agreed to!
if r == 2*r and r != 0.0:
raise OverflowError
Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_complexobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_complexobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_complexobject.py Sun Dec 12 18:11:19 2010
@@ -1,5 +1,6 @@
import py
-from pypy.objspace.std import complexobject as cobj
+from pypy.objspace.std.complexobject import W_ComplexObject, \
+ pow__Complex_Complex_ANY
from pypy.objspace.std import complextype as cobjtype
from pypy.objspace.std.multimethod import FailedToImplement
from pypy.objspace.std.stringobject import W_StringObject
@@ -11,7 +12,7 @@
def _test_instantiation(self):
def _t_complex(r=0.0,i=0.0):
- c = cobj.W_ComplexObject(r, i)
+ c = W_ComplexObject(r, i)
assert c.real == float(r) and c.imag == float(i)
pairs = (
(1, 1),
@@ -41,21 +42,31 @@
def test_pow(self):
- assert cobj._pow((0.0,2.0),(0.0,0.0)) == (1.0,0.0)
- assert cobj._pow((0.0,0.0),(2.0,0.0)) == (0.0,0.0)
- rr, ir = cobj._pow((0.0,1.0),(2.0,0.0))
+ def _pow((r1, i1), (r2, i2)):
+ w_res = W_ComplexObject(r1, i1).pow(W_ComplexObject(r2, i2))
+ return w_res.realval, w_res.imagval
+ assert _pow((0.0,2.0),(0.0,0.0)) == (1.0,0.0)
+ assert _pow((0.0,0.0),(2.0,0.0)) == (0.0,0.0)
+ rr, ir = _pow((0.0,1.0),(2.0,0.0))
assert abs(-1.0 - rr) < EPS
assert abs(0.0 - ir) < EPS
- assert cobj._powu((0.0,2.0),0) == (1.0,0.0)
- assert cobj._powu((0.0,0.0),2) == (0.0,0.0)
- assert cobj._powu((0.0,1.0),2) == (-1.0,0.0)
- assert cobj._powi((0.0,2.0),0) == (1.0,0.0)
- assert cobj._powi((0.0,0.0),2) == (0.0,0.0)
- assert cobj._powi((0.0,1.0),2) == (-1.0,0.0)
- c = cobj.W_ComplexObject(0.0,1.0)
- p = cobj.W_ComplexObject(2.0,0.0)
- r = cobj.pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None))
+ def _powu((r1, i1), n):
+ w_res = W_ComplexObject(r1, i1).pow_positive_int(n)
+ return w_res.realval, w_res.imagval
+ assert _powu((0.0,2.0),0) == (1.0,0.0)
+ assert _powu((0.0,0.0),2) == (0.0,0.0)
+ assert _powu((0.0,1.0),2) == (-1.0,0.0)
+
+ def _powi((r1, i1), n):
+ w_res = W_ComplexObject(r1, i1).pow_int(n)
+ return w_res.realval, w_res.imagval
+ assert _powi((0.0,2.0),0) == (1.0,0.0)
+ assert _powi((0.0,0.0),2) == (0.0,0.0)
+ assert _powi((0.0,1.0),2) == (-1.0,0.0)
+ c = W_ComplexObject(0.0,1.0)
+ p = W_ComplexObject(2.0,0.0)
+ r = pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None))
assert r.realval == -1.0
assert r.imagval == 0.0
Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py Sun Dec 12 18:11:19 2010
@@ -134,8 +134,6 @@
assert string_to_bigint('1891234174197319').tolong() == 1891234174197319
def test_string_to_float(self):
- def string_to_float(x):
- return interp_string_to_float(self.space, x)
assert string_to_float('0') == 0.0
assert string_to_float('1') == 1.0
assert string_to_float('-1.5') == -1.5
@@ -183,3 +181,4 @@
print repr(s)
if s.strip(): # empty s raises OperationError directly
py.test.raises(ParseStringError, string_to_float, s)
+ py.test.raises(ParseStringError, string_to_float, "")
Modified: pypy/branch/fast-forward/pypy/rlib/rmd5.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rmd5.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rmd5.py Sun Dec 12 18:11:19 2010
@@ -29,20 +29,30 @@
if r_uint.BITS == 32:
- def _mask(x):
- "No-op on 32-bit platforms."
- return x
-else:
- def _mask(x):
- "Masks the r_uint value x to keep only the lowest 32 bits."
- return x & r_uint(0xffffffff)
-
+ def _rotateLeft(x, n):
+ "Rotate x (32 bit) left n bits circularly."
+ return (x << n) | (x >> (32-n))
-def _rotateLeft(x, n):
- "Rotate x (32 bit) left n bits circularly."
-
- x = _mask(x)
- return (x << n) | (x >> (32-n))
+else:
+ def _rotateLeft_emulator(x, n):
+ x &= 0xFFFFFFFF
+ return (x << n) | (x >> (32-n))
+
+ # ----- start of custom code, think about something better... -----
+ from pypy.rpython.lltypesystem import lltype, rffi
+ from pypy.translator.tool.cbuild import ExternalCompilationInfo
+ eci = ExternalCompilationInfo(post_include_bits=["""
+static unsigned long pypy__rotateLeft(unsigned long x, long n) {
+ unsigned int x1 = x; /* arithmetic directly on int */
+ int n1 = n;
+ return (x1 << n1) | (x1 >> (32-n1));
+}
+"""])
+ _rotateLeft = rffi.llexternal(
+ "pypy__rotateLeft", [lltype.Unsigned, lltype.Signed], lltype.Unsigned,
+ _callable=_rotateLeft_emulator, compilation_info=eci,
+ _nowrapper=True, pure_function=True)
+ # we expect the function _rotateLeft to be actually inlined
def _state2string(a, b, c, d):
Modified: pypy/branch/fast-forward/pypy/rlib/rmmap.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rmmap.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rmmap.py Sun Dec 12 18:11:19 2010
@@ -67,7 +67,7 @@
constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
'DUPLICATE_SAME_ACCESS', 'MEM_COMMIT', 'MEM_RESERVE',
- 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE']
+ 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE', 'PAGE_NOACCESS']
for name in constant_names:
setattr(CConfig, name, rffi_platform.ConstantInteger(name))
@@ -100,8 +100,11 @@
sandboxsafe=True, threadsafe=False)
return unsafe, safe
-def winexternal(name, args, result):
- return rffi.llexternal(name, args, result, compilation_info=CConfig._compilation_info_, calling_conv='win')
+def winexternal(name, args, result, **kwargs):
+ return rffi.llexternal(name, args, result,
+ compilation_info=CConfig._compilation_info_,
+ calling_conv='win',
+ **kwargs)
PTR = rffi.CCHARP
@@ -190,9 +193,17 @@
VirtualAlloc = winexternal('VirtualAlloc',
[rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD],
rffi.VOIDP)
- VirtualProtect = winexternal('VirtualProtect',
- [rffi.VOIDP, rffi.SIZE_T, DWORD, LPDWORD],
- BOOL)
+ # VirtualProtect is used in llarena and should not release the GIL
+ _VirtualProtect = winexternal('VirtualProtect',
+ [rffi.VOIDP, rffi.SIZE_T, DWORD, LPDWORD],
+ BOOL,
+ _nowrapper=True)
+ def VirtualProtect(addr, size, mode, oldmode_ptr):
+ return _VirtualProtect(addr,
+ rffi.cast(rffi.SIZE_T, size),
+ rffi.cast(DWORD, mode),
+ oldmode_ptr)
+ VirtualProtect._annspecialcase_ = 'specialize:ll'
VirtualFree = winexternal('VirtualFree',
[rffi.VOIDP, rffi.SIZE_T, DWORD], BOOL)
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py Sun Dec 12 18:11:19 2010
@@ -26,6 +26,7 @@
self.objectptrs = {} # {offset: ptr-to-container}
self.objectsizes = {} # {offset: size}
self.freed = False
+ self.protect_inaccessible = None
self.reset(zero)
def __repr__(self):
@@ -59,6 +60,8 @@
def check(self):
if self.freed:
raise ArenaError("arena was already freed")
+ if self.protect_inaccessible is not None:
+ raise ArenaError("arena is currently arena_protect()ed")
def _getid(self):
address, length = self.usagemap.buffer_info()
@@ -127,6 +130,21 @@
def mark_freed(self):
self.freed = True # this method is a hook for tests
+ def set_protect(self, inaccessible):
+ if inaccessible:
+ assert self.protect_inaccessible is None
+ saved = []
+ for ptr in self.objectptrs.values():
+ obj = ptr._obj
+ saved.append((obj, obj._protect()))
+ self.protect_inaccessible = saved
+ else:
+ assert self.protect_inaccessible is not None
+ saved = self.protect_inaccessible
+ for obj, storage in saved:
+ obj._unprotect(storage)
+ self.protect_inaccessible = None
+
class fakearenaaddress(llmemory.fakeaddress):
def __init__(self, arena, offset):
@@ -365,6 +383,16 @@
"""
return Arena(ptr.arena.nbytes, False).getaddr(0)
+def arena_protect(arena_addr, size, inaccessible):
+ """For debugging, set or reset memory protection on an arena.
+ For now, the starting point and size should reference the whole arena.
+ The value of 'inaccessible' is a boolean.
+ """
+ arena_addr = getfakearenaaddress(arena_addr)
+ assert arena_addr.offset == 0
+ assert size == arena_addr.arena.nbytes
+ arena_addr.arena.set_protect(inaccessible)
+
# ____________________________________________________________
#
# Translation support: the functions above turn into the code below.
@@ -475,6 +503,42 @@
# them immediately.
clear_large_memory_chunk = llmemory.raw_memclear
+if os.name == "posix":
+ from pypy.translator.tool.cbuild import ExternalCompilationInfo
+ _eci = ExternalCompilationInfo(includes=['sys/mman.h'])
+ raw_mprotect = rffi.llexternal('mprotect',
+ [llmemory.Address, rffi.SIZE_T, rffi.INT],
+ rffi.INT,
+ sandboxsafe=True, _nowrapper=True,
+ compilation_info=_eci)
+ def llimpl_protect(addr, size, inaccessible):
+ if inaccessible:
+ prot = 0
+ else:
+ from pypy.rlib.rmmap import PROT_READ, PROT_WRITE
+ prot = PROT_READ | PROT_WRITE
+ raw_mprotect(addr, rffi.cast(rffi.SIZE_T, size),
+ rffi.cast(rffi.INT, prot))
+ # ignore potential errors
+ has_protect = True
+
+elif os.name == 'nt':
+ def llimpl_protect(addr, size, inaccessible):
+ from pypy.rlib.rmmap import VirtualProtect, LPDWORD
+ if inaccessible:
+ from pypy.rlib.rmmap import PAGE_NOACCESS as newprotect
+ else:
+ from pypy.rlib.rmmap import PAGE_READWRITE as newprotect
+ arg = lltype.malloc(LPDWORD.TO, 1, zero=True, flavor='raw')
+ VirtualProtect(rffi.cast(rffi.VOIDP, addr),
+ size, newprotect, arg)
+ # ignore potential errors
+ lltype.free(arg, flavor='raw')
+ has_protect = True
+
+else:
+ has_protect = False
+
llimpl_malloc = rffi.llexternal('malloc', [lltype.Signed], llmemory.Address,
sandboxsafe=True, _nowrapper=True)
@@ -544,6 +608,21 @@
'll_arena.arena_new_view', llimpl=llimpl_arena_new_view,
llfakeimpl=arena_new_view, sandboxsafe=True)
+def llimpl_arena_protect(addr, size, inaccessible):
+ if has_protect:
+ # do some alignment
+ start = rffi.cast(lltype.Signed, addr)
+ end = start + size
+ start = (start + 4095) & ~ 4095
+ end = end & ~ 4095
+ if end > start:
+ llimpl_protect(rffi.cast(llmemory.Address, start), end-start,
+ inaccessible)
+register_external(arena_protect, [llmemory.Address, lltype.Signed,
+ lltype.Bool], lltype.Void,
+ 'll_arena.arena_protect', llimpl=llimpl_arena_protect,
+ llfakeimpl=arena_protect, sandboxsafe=True)
+
def llimpl_getfakearenaaddress(addr):
return addr
register_external(getfakearenaaddress, [llmemory.Address], llmemory.Address,
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py Sun Dec 12 18:11:19 2010
@@ -1388,6 +1388,15 @@
self._check() # no double-frees
self._storage = None
+ def _protect(self):
+ result = self._storage
+ self._free() # no double-frees or double-protects
+ return result
+
+ def _unprotect(self, saved_storage):
+ assert self._storage is None
+ self._storage = saved_storage
+
def _was_freed(self):
if self._storage is None:
return True
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py Sun Dec 12 18:11:19 2010
@@ -242,10 +242,7 @@
FAST_RFIND = 2
-# XXX: This should be set to the number of bits in a long. Having a lower
-# value here doesn't break anything, it just decreases the accuracy of the
-# bloom filter heuristic, which results in a worse runtime (but correct results)
-BLOOM_WIDTH = 32
+from pypy.rlib.rarithmetic import LONG_BIT as BLOOM_WIDTH
def bloom_add(mask, c):
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llarena.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llarena.py Sun Dec 12 18:11:19 2010
@@ -6,6 +6,8 @@
from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
from pypy.rpython.lltypesystem.llarena import arena_shrink_obj
+from pypy.rpython.lltypesystem.llarena import arena_protect, has_protect
+from pypy.translator.c.test import test_genc, test_standalone
def test_arena():
S = lltype.Struct('S', ('x',lltype.Signed))
@@ -265,8 +267,7 @@
assert res == 42
def test_compiled():
- from pypy.translator.c.test.test_genc import compile
- fn = compile(test_look_inside_object, [])
+ fn = test_genc.compile(test_look_inside_object, [])
res = fn()
assert res == 42
@@ -282,3 +283,51 @@
arena_reserve(a, size_gc_header + llmemory.sizeof(S, 10))
arena_shrink_obj(a, size_gc_header + llmemory.sizeof(S, 5))
arena_reset(a, size_gc_header + llmemory.sizeof(S, 5), False)
+
+def test_arena_protect():
+ a = arena_malloc(100, False)
+ S = lltype.Struct('S', ('x', lltype.Signed))
+ arena_reserve(a, llmemory.sizeof(S))
+ p = llmemory.cast_adr_to_ptr(a, lltype.Ptr(S))
+ p.x = 123
+ assert p.x == 123
+ arena_protect(a, 100, True)
+ py.test.raises(ArenaError, arena_reserve, a + 48, llmemory.sizeof(S))
+ py.test.raises(RuntimeError, "p.x")
+ py.test.raises(RuntimeError, "p.x = 124")
+ arena_protect(a, 100, False)
+ assert p.x == 123
+ p.x = 125
+ assert p.x == 125
+
+
+class TestStandalone(test_standalone.StandaloneTests):
+ def test_compiled_arena_protect(self):
+ import os
+ from pypy.translator.c.test.test_genc import compile
+ S = lltype.Struct('S', ('x', lltype.Signed))
+ #
+ def fn(argv):
+ testrun = int(argv[1])
+ a = arena_malloc(65536, False)
+ arena_reserve(a, llmemory.sizeof(S))
+ p = llmemory.cast_adr_to_ptr(a + 23432, lltype.Ptr(S))
+ p.x = 123
+ assert p.x == 123
+ arena_protect(a, 65536, True)
+ result = 0
+ if testrun == 1:
+ print p.x # segfault
+ if testrun == 2:
+ p.x = 124 # segfault
+ arena_protect(a, 65536, False)
+ p.x += 10
+ print p.x
+ return 0
+ #
+ t, cbuilder = self.compile(fn)
+ data = cbuilder.cmdexec('0')
+ assert data == '133\n'
+ if has_protect:
+ cbuilder.cmdexec('1', expect_crash=True)
+ cbuilder.cmdexec('2', expect_crash=True)
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py Sun Dec 12 18:11:19 2010
@@ -36,6 +36,12 @@
self.finalizer_lock_count = 0
self.run_finalizers = self.AddressDeque()
+ def post_setup(self):
+ # More stuff that needs to be initialized when the GC is already
+ # fully working. (Only called by gctransform/framework for now.)
+ from pypy.rpython.memory.gc import env
+ self.DEBUG = env.read_from_env('PYPY_GC_DEBUG')
+
def _teardown(self):
pass
@@ -48,7 +54,8 @@
# The following flag enables costly consistency checks after each
# collection. It is automatically set to True by test_gc.py. The
# checking logic is translatable, so the flag can be set to True
- # here before translation.
+ # here before translation. At run-time, if PYPY_GC_DEBUG is set,
+ # then it is also set to True.
DEBUG = False
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/env.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/env.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/env.py Sun Dec 12 18:11:19 2010
@@ -4,7 +4,7 @@
import os, sys
from pypy.rlib.rarithmetic import r_uint
from pypy.rlib.debug import debug_print, debug_start, debug_stop
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rpython.lltypesystem.lloperation import llop
# ____________________________________________________________
@@ -110,15 +110,9 @@
# ____________________________________________________________
# Estimation of the nursery size, based on the L2 cache.
-def best_nursery_size_for_L2cache(L2cache):
- # Heuristically, the best nursery size to choose is about half
- # of the L2 cache. XXX benchmark some more.
- if L2cache > 0:
- return L2cache // 2
- else:
- return -1
+# ---------- Linux2 ----------
-def get_L2cache_linux2(filename):
+def get_L2cache_linux2(filename="/proc/cpuinfo"):
debug_start("gc-hardware")
L2cache = sys.maxint
try:
@@ -189,61 +183,66 @@
pos += 1
return pos
+# ---------- Darwin ----------
-if sys.platform == 'linux2':
- def estimate_best_nursery_size():
- """Try to estimate the best nursery size at run-time, depending
- on the machine we are running on. Linux code."""
- L2cache = get_L2cache_linux2('/proc/cpuinfo')
- return best_nursery_size_for_L2cache(L2cache)
-
-elif sys.platform == 'darwin':
- from pypy.rpython.lltypesystem import rffi
-
- sysctlbyname = rffi.llexternal('sysctlbyname',
- [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
- rffi.VOIDP, rffi.SIZE_T],
- rffi.INT,
- sandboxsafe=True)
-
- def estimate_best_nursery_size():
- """Try to estimate the best nursery size at run-time, depending
- on the machine we are running on.
- """
- debug_start("gc-hardware")
- L2cache = 0
- l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
+sysctlbyname = rffi.llexternal('sysctlbyname',
+ [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
+ rffi.VOIDP, rffi.SIZE_T],
+ rffi.INT,
+ sandboxsafe=True)
+def get_L2cache_darwin():
+ """Try to estimate the best nursery size at run-time, depending
+ on the machine we are running on.
+ """
+ debug_start("gc-hardware")
+ L2cache = 0
+ l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
+ try:
+ len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
try:
- len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
- try:
- size = rffi.sizeof(rffi.LONGLONG)
- l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
- len_p[0] = rffi.cast(rffi.SIZE_T, size)
- # XXX a hack for llhelper not being robust-enough
- result = sysctlbyname("hw.l2cachesize",
- rffi.cast(rffi.VOIDP, l2cache_p),
- len_p,
- lltype.nullptr(rffi.VOIDP.TO),
- rffi.cast(rffi.SIZE_T, 0))
- if (rffi.cast(lltype.Signed, result) == 0 and
- rffi.cast(lltype.Signed, len_p[0]) == size):
- L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
- if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
- L2cache = 0 # overflow!
- finally:
- lltype.free(len_p, flavor='raw')
+ size = rffi.sizeof(rffi.LONGLONG)
+ l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
+ len_p[0] = rffi.cast(rffi.SIZE_T, size)
+ # XXX a hack for llhelper not being robust-enough
+ result = sysctlbyname("hw.l2cachesize",
+ rffi.cast(rffi.VOIDP, l2cache_p),
+ len_p,
+ lltype.nullptr(rffi.VOIDP.TO),
+ rffi.cast(rffi.SIZE_T, 0))
+ if (rffi.cast(lltype.Signed, result) == 0 and
+ rffi.cast(lltype.Signed, len_p[0]) == size):
+ L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
+ if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
+ L2cache = 0 # overflow!
finally:
- lltype.free(l2cache_p, flavor='raw')
- debug_print("L2cache =", L2cache)
- debug_stop("gc-hardware")
- if L2cache > 0:
- return L2cache
- else:
- # Print a top-level warning even in non-debug builds
- llop.debug_print(lltype.Void,
- "Warning: cannot find your CPU L2 cache size with sysctl()")
- return -1
+ lltype.free(len_p, flavor='raw')
+ finally:
+ lltype.free(l2cache_p, flavor='raw')
+ debug_print("L2cache =", L2cache)
+ debug_stop("gc-hardware")
+ if L2cache > 0:
+ return L2cache
+ else:
+ # Print a top-level warning even in non-debug builds
+ llop.debug_print(lltype.Void,
+ "Warning: cannot find your CPU L2 cache size with sysctl()")
+ return -1
-else:
- def estimate_best_nursery_size():
- return -1 # XXX implement me for other platforms
+# --------------------
+
+get_L2cache = globals().get('get_L2cache_' + sys.platform,
+ lambda: -1) # implement me for other platforms
+
+def best_nursery_size_for_L2cache(L2cache):
+ # Heuristically, the best nursery size to choose is about half
+ # of the L2 cache.
+ if L2cache > 0:
+ return L2cache // 2
+ else:
+ return -1
+
+def estimate_best_nursery_size():
+ """Try to estimate the best nursery size at run-time, depending
+ on the machine we are running on. Linux code."""
+ L2cache = get_L2cache()
+ return best_nursery_size_for_L2cache(L2cache)
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/minimark.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/minimark.py Sun Dec 12 18:11:19 2010
@@ -3,7 +3,8 @@
Environment variables can be used to fine-tune the following parameters:
PYPY_GC_NURSERY The nursery size. Defaults to half the size of
- the L2 cache. Try values like '1.2MB'.
+ the L2 cache. Try values like '1.2MB'. Small values
+ (like 1 or 1KB) are useful for debugging.
PYPY_GC_MAJOR_COLLECT Major collection memory factor. Default is '1.82',
which means trigger a major collection when the
@@ -32,6 +33,11 @@
limit. Useful to avoid spending all the time in
the GC in very small programs. Defaults to 8
times the nursery.
+
+ PYPY_GC_DEBUG Enable extra checks around collections that are
+ too slow for normal use. Values are 0 (off),
+ 1 (on major collections) or 2 (also on minor
+ collections).
"""
# XXX Should find a way to bound the major collection threshold by the
# XXX total addressable size. Maybe by keeping some minimarkpage arenas
@@ -223,7 +229,8 @@
self.nursery = NULL
self.nursery_free = NULL
self.nursery_top = NULL
- self.debug_always_do_minor_collect = False
+ self.debug_tiny_nursery = -1
+ self.debug_rotating_nurseries = None
#
# The ArenaCollection() handles the nonmovable objects allocation.
if ArenaCollectionClass is None:
@@ -291,15 +298,20 @@
# From there on, the GC is fully initialized and the code
# below can use it
newsize = env.read_from_env('PYPY_GC_NURSERY')
- # PYPY_GC_NURSERY=1 forces a minor collect for every malloc.
- # Useful to debug external factors, like trackgcroot or the
- # handling of the write barrier.
- self.debug_always_do_minor_collect = newsize == 1
+ # PYPY_GC_NURSERY=smallvalue means that minor collects occur
+ # very frequently; the extreme case is PYPY_GC_NURSERY=1, which
+ # forces a minor collect for every malloc. Useful to debug
+ # external factors, like trackgcroot or the handling of the write
+ # barrier. Implemented by still using 'minsize' for the nursery
+ # size (needed to handle e.g. mallocs of 8249 words) but hacking
+ # at the current nursery position in collect_and_reserve().
if newsize <= 0:
newsize = env.estimate_best_nursery_size()
if newsize <= 0:
newsize = defaultsize
- newsize = max(newsize, minsize)
+ if newsize < minsize:
+ self.debug_tiny_nursery = newsize & ~(WORD-1)
+ newsize = minsize
#
major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
if major_coll > 1.0:
@@ -332,17 +344,24 @@
self.allocate_nursery()
- def allocate_nursery(self):
- debug_start("gc-set-nursery-size")
- debug_print("nursery size:", self.nursery_size)
+ def _nursery_memory_size(self):
+ extra = self.nonlarge_gcptrs_max + 1
+ return self.nursery_size + extra
+
+ def _alloc_nursery(self):
# the start of the nursery: we actually allocate a bit more for
# the nursery than really needed, to simplify pointer arithmetic
# in malloc_fixedsize_clear(). The few extra pages are never used
# anyway so it doesn't even count.
- extra = self.nonlarge_gcptrs_max + 1
- self.nursery = llarena.arena_malloc(self.nursery_size + extra, 2)
- if not self.nursery:
+ nursery = llarena.arena_malloc(self._nursery_memory_size(), 2)
+ if not nursery:
raise MemoryError("cannot allocate nursery")
+ return nursery
+
+ def allocate_nursery(self):
+ debug_start("gc-set-nursery-size")
+ debug_print("nursery size:", self.nursery_size)
+ self.nursery = self._alloc_nursery()
# the current position in the nursery:
self.nursery_free = self.nursery
# the end of the nursery:
@@ -376,6 +395,40 @@
return bounded
+ def post_setup(self):
+ # set up extra stuff for PYPY_GC_DEBUG.
+ MovingGCBase.post_setup(self)
+ if self.DEBUG and llarena.has_protect:
+ # gc debug mode: allocate 23 nurseries instead of just 1,
+ # and use them alternatively, while mprotect()ing the unused
+ # ones to detect invalid access.
+ debug_start("gc-debug")
+ self.debug_rotating_nurseries = []
+ for i in range(22):
+ nurs = self._alloc_nursery()
+ llarena.arena_protect(nurs, self._nursery_memory_size(), True)
+ self.debug_rotating_nurseries.append(nurs)
+ debug_print("allocated", len(self.debug_rotating_nurseries),
+ "extra nurseries")
+ debug_stop("gc-debug")
+
+ def debug_rotate_nursery(self):
+ if self.debug_rotating_nurseries is not None:
+ debug_start("gc-debug")
+ oldnurs = self.nursery
+ llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
+ self.debug_rotating_nurseries.append(oldnurs)
+ #
+ newnurs = self.debug_rotating_nurseries.pop(0)
+ llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
+ self.nursery = newnurs
+ self.nursery_top = self.nursery + self.nursery_size
+ debug_print("switching from nursery", oldnurs,
+ "to nursery", self.nursery,
+ "size", self.nursery_size)
+ debug_stop("gc-debug")
+
+
def malloc_fixedsize_clear(self, typeid, size, can_collect=True,
needs_finalizer=False, contains_weakptr=False):
ll_assert(can_collect, "!can_collect")
@@ -513,8 +566,9 @@
self.nursery_free = result + totalsize
ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow")
#
- if self.debug_always_do_minor_collect:
- self.nursery_free = self.nursery_top
+ if self.debug_tiny_nursery >= 0: # for debugging
+ if self.nursery_top - self.nursery_free > self.debug_tiny_nursery:
+ self.nursery_free = self.nursery_top - self.debug_tiny_nursery
#
return result
collect_and_reserve._dont_inline_ = True
@@ -841,7 +895,7 @@
def remember_young_pointer(addr_struct, newvalue):
# 'addr_struct' is the address of the object in which we write.
# 'newvalue' is the address that we are going to write in there.
- if DEBUG:
+ if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
ll_assert(not self.is_in_nursery(addr_struct),
"nursery object with GCFLAG_NO_YOUNG_PTRS")
#
@@ -878,7 +932,7 @@
# 'addr_array' is the address of the object in which we write,
# which must have an array part; 'index' is the index of the
# item that is (or contains) the pointer that we write.
- if DEBUG:
+ if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
ll_assert(not self.is_in_nursery(addr_array),
"nursery array with GCFLAG_NO_YOUNG_PTRS")
objhdr = self.header(addr_array)
@@ -1000,13 +1054,14 @@
# All live nursery objects are out, and the rest dies. Fill
# the whole nursery with zero and reset the current nursery pointer.
llarena.arena_reset(self.nursery, self.nursery_size, 2)
+ self.debug_rotate_nursery()
self.nursery_free = self.nursery
#
debug_print("minor collect, total memory used:",
self.get_total_memory_used())
+ if self.DEBUG >= 2:
+ self.debug_check_consistency() # expensive!
debug_stop("gc-minor")
- if 0: # not we_are_translated():
- self.debug_check_consistency() # xxx expensive!
def collect_roots_in_nursery(self):
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py Sun Dec 12 18:11:19 2010
@@ -306,6 +306,16 @@
if item:
self._shape_decompressor.setaddr(item)
return
+ # there is a rare risk that the array contains *two* entries
+ # with the same key, one of which is dead (null value), and we
+ # found the dead one above. Solve this case by replacing all
+ # dead keys with nulls, sorting again, and then trying again.
+ replace_dead_entries_with_nulls(gcmapstart2, gcmapend2)
+ sort_gcmap(gcmapstart2, gcmapend2)
+ item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
+ if item:
+ self._shape_decompressor.setaddr(item)
+ return
# the item may have been not found because the main array was
# not sorted. Sort it and try again.
win32_follow_gcmap_jmp(gcmapstart, gcmapend)
@@ -401,6 +411,15 @@
rffi.cast(rffi.SIZE_T, arrayitemsize),
llhelper(QSORT_CALLBACK_PTR, _compare_gcmap_entries))
+def replace_dead_entries_with_nulls(start, end):
+ # replace the dead entries (null value) with a null key.
+ count = (end - start) // arrayitemsize - 1
+ while count >= 0:
+ item = start + count * arrayitemsize
+ if item.address[1] == llmemory.NULL:
+ item.address[0] = llmemory.NULL
+ count -= 1
+
if sys.platform == 'win32':
def win32_follow_gcmap_jmp(start, end):
# The initial gcmap table contains addresses to a JMP
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py Sun Dec 12 18:11:19 2010
@@ -189,6 +189,7 @@
# run-time initialization code
root_walker.setup_root_walker()
gcdata.gc.setup()
+ gcdata.gc.post_setup()
def frameworkgc__teardown():
# run-time teardown code for tests!
Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_os.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_os.py Sun Dec 12 18:11:19 2010
@@ -730,6 +730,22 @@
return extdef([traits.str, int, int], int, traits.ll_os_name('open'),
llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
+ @registering_if(os, 'getloadavg')
+ def register_os_getloadavg(self):
+ AP = rffi.CArrayPtr(lltype.Float)
+ c_getloadavg = self.llexternal('getloadavg', [AP, rffi.INT], rffi.INT)
+
+ def getloadavg_llimpl():
+ load = lltype.malloc(AP.TO, 3, flavor='raw')
+ r = c_getloadavg(load, 3)
+ result_tuple = load[0], load[1], load[2]
+ lltype.free(load, flavor='raw')
+ if r != 3:
+ raise OSError
+ return result_tuple
+ return extdef([], (float, float, float),
+ "ll_os.ll_getloadavg", llimpl=getloadavg_llimpl)
+
# ------------------------------- os.read -------------------------------
@registering(os.read)
@@ -887,6 +903,18 @@
llimpl=fdatasync_llimpl,
export_name="ll_os.ll_os_fdatasync")
+ @registering_if(os, 'fchdir')
+ def register_os_fchdir(self):
+ os_fchdir = self.llexternal('fchdir', [rffi.INT], rffi.INT)
+
+ def fchdir_llimpl(fd):
+ res = rffi.cast(rffi.LONG, os_fchdir(rffi.cast(rffi.INT, fd)))
+ if res < 0:
+ raise OSError(rposix.get_errno(), "fchdir failed")
+ return extdef([int], s_None,
+ llimpl=fchdir_llimpl,
+ export_name="ll_os.ll_os_fchdir")
+
@registering_str_unicode(os.access)
def register_os_access(self, traits):
os_access = self.llexternal(traits.posix_function_name('access'),
Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py (original)
+++ pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py Sun Dec 12 18:11:19 2010
@@ -755,3 +755,31 @@
for i in range(5):
res = func(i)
assert res == os.uname()[i]
+
+if hasattr(os, 'getloadavg'):
+ def test_os_getloadavg():
+ def does_stuff():
+ a, b, c = os.getloadavg()
+ print a, b, c
+ return a + b + c
+ f = compile(does_stuff, [])
+ res = f()
+ assert type(res) is float and res >= 0.0
+
+if hasattr(os, 'fchdir'):
+ def test_os_fchdir():
+ def does_stuff():
+ fd = os.open('/', os.O_RDONLY, 0400)
+ try:
+ os.fchdir(fd)
+ s = os.getcwd()
+ finally:
+ os.close(fd)
+ return s == '/'
+ f = compile(does_stuff, [])
+ localdir = os.getcwd()
+ try:
+ res = f()
+ finally:
+ os.chdir(localdir)
+ assert res == True
Modified: pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py (original)
+++ pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py Sun Dec 12 18:11:19 2010
@@ -148,6 +148,7 @@
if sys.platform == 'linux2': # on Mac, uses another (sandboxsafe) approach
expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420),
OSError(5232, "xyz"))
+ expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_DEBUG",), None)
g.close()
tail = f.read()
f.close()
More information about the Pypy-commit
mailing list