[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