[pypy-svn] r77067 - in pypy/branch/fast-forward: . pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/jit/tool pypy/module/_socket pypy/module/_socket/test pypy/module/_ssl pypy/module/_weakref pypy/module/_winreg pypy/module/array pypy/module/array/benchmark pypy/module/array/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/rlib pypy/rpython/lltypesystem pypy/rpython/module pypy/rpython/tool pypy/rpython/tool/test pypy/tool/release pypy/translator/c

afa at codespeak.net afa at codespeak.net
Tue Sep 14 16:34:20 CEST 2010


Author: afa
Date: Tue Sep 14 16:34:16 2010
New Revision: 77067

Added:
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/
      - copied from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/__init__.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/heap.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/heap.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intbounds.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/intbounds.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intutils.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/intutils.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/optimizer.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/rewrite.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/rewrite.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/virtualize.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/optimizeopt/virtualize.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_intbound.py
      - copied unchanged from r77066, pypy/trunk/pypy/jit/metainterp/test/test_intbound.py
   pypy/branch/fast-forward/pypy/module/pypyjit/test/randomized.py
      - copied unchanged from r77066, pypy/trunk/pypy/module/pypyjit/test/randomized.py
Removed:
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py
Modified:
   pypy/branch/fast-forward/   (props changed)
   pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py
   pypy/branch/fast-forward/pypy/jit/backend/model.py
   pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py
   pypy/branch/fast-forward/pypy/jit/metainterp/compile.py
   pypy/branch/fast-forward/pypy/jit/metainterp/jitdriver.py
   pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py
   pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py
   pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py
   pypy/branch/fast-forward/pypy/jit/tool/traceviewer.py
   pypy/branch/fast-forward/pypy/module/_socket/interp_func.py
   pypy/branch/fast-forward/pypy/module/_socket/interp_socket.py
   pypy/branch/fast-forward/pypy/module/_socket/test/test_sock_app.py
   pypy/branch/fast-forward/pypy/module/_ssl/interp_ssl.py
   pypy/branch/fast-forward/pypy/module/_weakref/interp__weakref.py
   pypy/branch/fast-forward/pypy/module/_winreg/interp_winreg.py
   pypy/branch/fast-forward/pypy/module/array/benchmark/Makefile   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimg.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/loop.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sum.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/interp_array.py
   pypy/branch/fast-forward/pypy/module/array/test/test_array.py
   pypy/branch/fast-forward/pypy/module/array/test/test_array_old.py   (props changed)
   pypy/branch/fast-forward/pypy/module/pypyjit/interp_jit.py
   pypy/branch/fast-forward/pypy/module/pypyjit/policy.py
   pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py
   pypy/branch/fast-forward/pypy/rlib/jit.py
   pypy/branch/fast-forward/pypy/rlib/rmmap.py
   pypy/branch/fast-forward/pypy/rlib/rsocket.py
   pypy/branch/fast-forward/pypy/rlib/rwin32.py
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_os_stat.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_win32file.py
   pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py
   pypy/branch/fast-forward/pypy/rpython/tool/test/test_rffi_platform.py
   pypy/branch/fast-forward/pypy/tool/release/force-builds.py
   pypy/branch/fast-forward/pypy/translator/c/database.py
Log:
Merge from trunk
--Cette ligne, et les suivantes ci-dessous, seront ignorées--

_M   .
M    pypy/module/_weakref/interp__weakref.py
M    pypy/module/_socket/test/test_sock_app.py
M    pypy/module/_socket/interp_socket.py
M    pypy/module/_socket/interp_func.py
M    pypy/module/_winreg/interp_winreg.py
M    pypy/module/_ssl/interp_ssl.py
A  + pypy/module/pypyjit/test/randomized.py
M    pypy/module/pypyjit/test/test_pypy_c.py
M    pypy/module/pypyjit/policy.py
M    pypy/module/pypyjit/interp_jit.py
_M   pypy/module/array/test/test_array_old.py
M    pypy/module/array/test/test_array.py
M    pypy/module/array/interp_array.py
_M   pypy/module/array/benchmark/sumtst.c
_M   pypy/module/array/benchmark/intimgtst.c
_M   pypy/module/array/benchmark/sum.c
_M   pypy/module/array/benchmark/sumtst.py
_M   pypy/module/array/benchmark/intimg.c
_M   pypy/module/array/benchmark/intimgtst.py
_M   pypy/module/array/benchmark/loop.c
_M   pypy/module/array/benchmark/Makefile
M    pypy/jit/backend/test/runner_test.py
M    pypy/jit/backend/x86/regalloc.py
M    pypy/jit/backend/x86/runner.py
M    pypy/jit/backend/x86/assembler.py
M    pypy/jit/backend/model.py
M    pypy/jit/backend/llgraph/llimpl.py
M    pypy/jit/backend/llgraph/runner.py
M    pypy/jit/metainterp/compile.py
M    pypy/jit/metainterp/test/test_recursive.py
M    pypy/jit/metainterp/test/test_basic.py
M    pypy/jit/metainterp/test/test_resume.py
M    pypy/jit/metainterp/test/test_warmstate.py
A  + pypy/jit/metainterp/test/test_intbound.py
M    pypy/jit/metainterp/test/test_optimizeopt.py
M    pypy/jit/metainterp/test/test_compile.py
M    pypy/jit/metainterp/pyjitpl.py
A  + pypy/jit/metainterp/optimizeopt
A  + pypy/jit/metainterp/optimizeopt/intutils.py
A  + pypy/jit/metainterp/optimizeopt/heap.py
A  + pypy/jit/metainterp/optimizeopt/virtualize.py
A  + pypy/jit/metainterp/optimizeopt/__init__.py
A  + pypy/jit/metainterp/optimizeopt/rewrite.py
A  + pypy/jit/metainterp/optimizeopt/optimizer.py
A  + pypy/jit/metainterp/optimizeopt/intbounds.py
M    pypy/jit/metainterp/jitdriver.py
M    pypy/jit/metainterp/warmstate.py
M    pypy/jit/metainterp/warmspot.py
D    pypy/jit/metainterp/optimizeopt.py
M    pypy/jit/tool/traceviewer.py
M    pypy/rlib/rsocket.py
M    pypy/rlib/rmmap.py
M    pypy/rlib/rwin32.py
M    pypy/rlib/jit.py
M    pypy/rlib/_rsocket_rffi.py
M    pypy/translator/c/database.py
M    pypy/rpython/tool/test/test_rffi_platform.py
M    pypy/rpython/tool/rffi_platform.py
M    pypy/rpython/lltypesystem/rffi.py
M    pypy/rpython/module/ll_os.py
M    pypy/rpython/module/ll_win32file.py
M    pypy/rpython/module/ll_os_stat.py
M    pypy/tool/release/force-builds.py


Modified: pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py	Tue Sep 14 16:34:16 2010
@@ -128,7 +128,7 @@
     'getarrayitem_raw_pure' : (('ref', 'int'), 'intorptr'),
     'arraylen_gc'     : (('ref',), 'int'),
     'call'            : (('ref', 'varargs'), 'intorptr'),
-    'call_assembler'  : (('ref', 'varargs'), 'intorptr'),
+    'call_assembler'  : (('varargs',), 'intorptr'),
     'cond_call_gc_wb' : (('ptr', 'ptr'), None),
     'oosend'          : (('varargs',), 'intorptr'),
     'oosend_pure'     : (('varargs',), 'intorptr'),
@@ -165,10 +165,13 @@
         self.inputargs = []
         self.operations = []
 
+    def getargtypes(self):
+        return [v.concretetype for v in self.inputargs]
+
     def __repr__(self):
         lines = []
         self.as_text(lines, 1)
-        return 'CompiledLoop:\n%s' % '\n'.join(lines)
+        return 'CompiledLoop %s:\n%s' % (self.inputargs, '\n'.join(lines))
 
     def as_text(self, lines, indent):
         for op in self.operations:
@@ -839,6 +842,8 @@
     def op_call_assembler(self, loop_token, *args):
         global _last_exception
         assert not self._forced
+        loop_token = self.cpu._redirected_call_assembler.get(loop_token,
+                                                             loop_token)
         self._may_force = self.opindex
         try:
             inpargs = _from_opaque(loop_token._llgraph_compiled_version).inputargs
@@ -861,6 +866,21 @@
                 vable = args[jd.index_of_virtualizable]
             else:
                 vable = lltype.nullptr(llmemory.GCREF.TO)
+            #
+            # Emulate the fast path
+            if failindex == self.cpu.done_with_this_frame_int_v:
+                reset_vable(jd, vable)
+                return self.cpu.get_latest_value_int(0)
+            if failindex == self.cpu.done_with_this_frame_ref_v:
+                reset_vable(jd, vable)
+                return self.cpu.get_latest_value_ref(0)
+            if failindex == self.cpu.done_with_this_frame_float_v:
+                reset_vable(jd, vable)
+                return self.cpu.get_latest_value_float(0)
+            if failindex == self.cpu.done_with_this_frame_void_v:
+                reset_vable(jd, vable)
+                return None
+            #
             assembler_helper_ptr = jd.assembler_helper_adr.ptr  # fish
             try:
                 return assembler_helper_ptr(failindex, vable)
@@ -1480,6 +1500,17 @@
     else:
         return 0
 
+def reset_vable(jd, vable):
+    if jd.index_of_virtualizable != -1:
+        fielddescr = jd.vable_token_descr
+        do_setfield_gc_int(vable, fielddescr.ofs, 0)
+
+def redirect_call_assembler(cpu, oldlooptoken, newlooptoken):
+    OLD = _from_opaque(oldlooptoken._llgraph_compiled_version).getargtypes()
+    NEW = _from_opaque(newlooptoken._llgraph_compiled_version).getargtypes()
+    assert OLD == NEW
+    cpu._redirected_call_assembler[oldlooptoken] = newlooptoken
+
 # ____________________________________________________________
 
 

Modified: pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py	Tue Sep 14 16:34:16 2010
@@ -102,6 +102,7 @@
         llimpl._llinterp = LLInterpreter(self.rtyper)
         self._future_values = []
         self._descrs = {}
+        self._redirected_call_assembler = {}
 
     def _freeze_(self):
         assert self.translate_support_code
@@ -169,8 +170,8 @@
                 elif isinstance(x, history.ConstFloat):
                     llimpl.compile_add_float_const(c, x.value)
                 else:
-                    raise Exception("%s args contain: %r" % (op.getopname(),
-                                                             x))
+                    raise Exception("'%s' args contain: %r" % (op.getopname(),
+                                                               x))
             if op.is_guard():
                 faildescr = op.descr
                 assert isinstance(faildescr, history.AbstractFailDescr)
@@ -260,6 +261,11 @@
     def clear_latest_values(self, count):
         llimpl.frame_clear_latest_values(self.latest_frame, count)
 
+    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
+        if we_are_translated():
+            raise ValueError("CALL_ASSEMBLER not supported")
+        llimpl.redirect_call_assembler(self, oldlooptoken, newlooptoken)
+
     # ----------
 
     def sizeof(self, S):

Modified: pypy/branch/fast-forward/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/model.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/model.py	Tue Sep 14 16:34:16 2010
@@ -107,6 +107,12 @@
         GUARD_NO_EXCEPTION.  (Returns a GCREF)"""        # XXX remove me
         raise NotImplementedError
 
+    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
+        """Redirect oldlooptoken to newlooptoken.  More precisely, it is
+        enough to redirect all CALL_ASSEMBLERs already compiled that call
+        oldlooptoken so that from now own they will call newlooptoken."""
+        raise NotImplementedError
+
     @staticmethod
     def sizeof(S):
         raise NotImplementedError

Modified: pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py	Tue Sep 14 16:34:16 2010
@@ -1777,7 +1777,7 @@
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
         ARGS = [lltype.Signed] * 10
         RES = lltype.Signed
-        self.cpu.portal_calldescr = self.cpu.calldescrof(
+        FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
             lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES)
         for i in range(10):
             self.cpu.set_future_value_int(i, i+1)
@@ -1816,7 +1816,7 @@
 
         ARGS = [lltype.Float, lltype.Float]
         RES = lltype.Float
-        self.cpu.portal_calldescr = self.cpu.calldescrof(
+        FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
             lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES)
         
         ops = '''
@@ -1824,6 +1824,7 @@
         f2 = float_add(f0, f1)
         finish(f2)'''
         loop = parse(ops)
+        done_number = self.cpu.get_fail_descr_number(loop.operations[-1].descr)
         looptoken = LoopToken()
         looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
@@ -1846,6 +1847,20 @@
         assert self.cpu.get_latest_value_float(0) == 13.5
         assert called
 
+        # test the fast path, which should not call assembler_helper()
+        del called[:]
+        self.cpu.done_with_this_frame_float_v = done_number
+        try:
+            othertoken = LoopToken()
+            self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
+            self.cpu.set_future_value_float(0, 1.2)
+            self.cpu.set_future_value_float(1, 3.2)
+            res = self.cpu.execute_token(othertoken)
+            assert self.cpu.get_latest_value_float(0) == 1.2 + 3.2
+            assert not called
+        finally:
+            del self.cpu.done_with_this_frame_float_v
+
     def test_raw_malloced_getarrayitem(self):
         ARRAY = rffi.CArray(lltype.Signed)
         descr = self.cpu.arraydescrof(ARRAY)
@@ -1870,6 +1885,78 @@
         assert a[5] == 12345
         lltype.free(a, flavor='raw')
 
+    def test_redirect_call_assembler(self):
+        called = []
+        def assembler_helper(failindex, virtualizable):
+            assert self.cpu.get_latest_value_float(0) == 1.25 + 3.25
+            called.append(failindex)
+            return 13.5
+
+        FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
+                                             lltype.Float))
+        class FakeJitDriverSD:
+            index_of_virtualizable = -1
+            _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
+            assembler_helper_adr = llmemory.cast_ptr_to_adr(
+                _assembler_helper_ptr)
+
+        ARGS = [lltype.Float, lltype.Float]
+        RES = lltype.Float
+        FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
+            lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES)
+        
+        ops = '''
+        [f0, f1]
+        f2 = float_add(f0, f1)
+        finish(f2)'''
+        loop = parse(ops)
+        looptoken = LoopToken()
+        looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
+        self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+        self.cpu.set_future_value_float(0, 1.25)
+        self.cpu.set_future_value_float(1, 2.35)
+        res = self.cpu.execute_token(looptoken)
+        assert self.cpu.get_latest_value_float(0) == 1.25 + 2.35
+        assert not called
+
+        ops = '''
+        [f4, f5]
+        f3 = call_assembler(f4, f5, descr=looptoken)
+        guard_not_forced()[]
+        finish(f3)
+        '''
+        loop = parse(ops, namespace=locals())
+        othertoken = LoopToken()
+        self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
+
+        # normal call_assembler: goes to looptoken
+        self.cpu.set_future_value_float(0, 1.25)
+        self.cpu.set_future_value_float(1, 3.25)
+        res = self.cpu.execute_token(othertoken)
+        assert self.cpu.get_latest_value_float(0) == 13.5
+        assert called
+        del called[:]
+
+        # compile a replacement
+        ops = '''
+        [f0, f1]
+        f2 = float_sub(f0, f1)
+        finish(f2)'''
+        loop = parse(ops)
+        looptoken2 = LoopToken()
+        looptoken2.outermost_jitdriver_sd = FakeJitDriverSD()
+        self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken2)
+
+        # install it
+        self.cpu.redirect_call_assembler(looptoken, looptoken2)
+
+        # now, our call_assembler should go to looptoken2
+        self.cpu.set_future_value_float(0, 6.0)
+        self.cpu.set_future_value_float(1, 1.5)    # 6.0-1.5 == 1.25+3.25
+        res = self.cpu.execute_token(othertoken)
+        assert self.cpu.get_latest_value_float(0) == 13.5
+        assert called
+
 
 class OOtypeBackendTest(BaseBackendTest):
 

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py	Tue Sep 14 16:34:16 2010
@@ -328,6 +328,7 @@
         looptoken._x86_direct_bootstrap_code = self.mc.tell()
         self._assemble_bootstrap_direct_call(arglocs, curadr,
                                              frame_depth+param_depth)
+        #
         debug_print("Loop #", looptoken.number, "has address",
                     looptoken._x86_loop_code, "to", self.mc.tell())
         self.mc.end_function()
@@ -527,7 +528,6 @@
                 assert isinstance(loc, StackLoc)
                 self.mc.MOVSD_bx(loc.value, xmmtmp.value)
         self.mc.JMP_l(jmpadr)
-        return adr_stackadjust
 
     def _assemble_bootstrap_direct_call_64(self, arglocs, jmpadr, stackdepth):
         # XXX: Very similar to _emit_call_64
@@ -580,9 +580,23 @@
                 # clobber the scratch register
                 self.mc.MOV(loc, X86_64_SCRATCH_REG)
 
+        finaljmp = self.mc.tell()
         self.mc.JMP(imm(jmpadr))
 
-        return adr_stackadjust
+    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
+        # some minimal sanity checking
+        oldnonfloatlocs, oldfloatlocs = oldlooptoken._x86_arglocs
+        newnonfloatlocs, newfloatlocs = newlooptoken._x86_arglocs
+        assert len(oldnonfloatlocs) == len(newnonfloatlocs)
+        assert len(oldfloatlocs) == len(newfloatlocs)
+        # we overwrite the instructions at the old _x86_direct_bootstrap_code
+        # to start with a JMP to the new _x86_direct_bootstrap_code.
+        # Ideally we should rather patch all existing CALLs, but well.
+        oldadr = oldlooptoken._x86_direct_bootstrap_code
+        target = newlooptoken._x86_direct_bootstrap_code
+        mc = codebuf.InMemoryCodeBuilder(oldadr, oldadr + 16)
+        mc.JMP(imm(target))
+        mc.done()
 
     def _assemble_bootstrap_code(self, inputargs, arglocs):
         nonfloatlocs, floatlocs = arglocs

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py	Tue Sep 14 16:34:16 2010
@@ -665,13 +665,11 @@
         self._consider_call(op, guard_op)
 
     def consider_call_assembler(self, op, guard_op):
-        portal_calldescr = self.assembler.cpu.portal_calldescr
-        size = portal_calldescr.get_result_size(self.translate_support_code)
-        #
         descr = op.descr
         assert isinstance(descr, LoopToken)
         jd = descr.outermost_jitdriver_sd
         assert jd is not None
+        size = jd.portal_calldescr.get_result_size(self.translate_support_code)
         vable_index = jd.index_of_virtualizable
         if vable_index >= 0:
             self.rm._sync_var(op.args[vable_index])

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py	Tue Sep 14 16:34:16 2010
@@ -134,6 +134,9 @@
         assert fail_index == fail_index_2
         return faildescr
 
+    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
+        self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
+
 class CPU386(AbstractX86CPU):
     WORD = 4
     NUM_REGS = 8

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	Tue Sep 14 16:34:16 2010
@@ -14,6 +14,7 @@
 from pypy.jit.metainterp.specnode import NotSpecNode, more_general_specnodes
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
+from pypy.jit.codewriter import heaptracker
 
 def giveup():
     from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole
@@ -57,12 +58,9 @@
     loop.inputargs = history.inputargs
     for box in loop.inputargs:
         assert isinstance(box, Box)
-    if start > 0:
-        ops = history.operations[start:]
-    else:
-        ops = history.operations
     # make a copy, because optimize_loop can mutate the ops and descrs
-    loop.operations = [op.clone() for op in ops]
+    h_ops = history.operations
+    loop.operations = [h_ops[i].clone() for i in range(start, len(h_ops))]
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
     loop_token = make_loop_token(len(loop.inputargs), jitdriver_sd)
@@ -550,3 +548,55 @@
         descr = target_loop_token.finishdescr
         new_op = ResOperation(rop.FINISH, op.args, None, descr=descr)
         new_loop.operations[-1] = new_op
+
+# ____________________________________________________________
+
+class PropagateExceptionDescr(AbstractFailDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        cpu = metainterp_sd.cpu
+        exception = cpu.grab_exc_value()
+        raise metainterp_sd.ExitFrameWithExceptionRef(cpu, exception)
+
+propagate_exception_descr = PropagateExceptionDescr()
+
+def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes):
+    """Make a LoopToken that corresponds to assembler code that just
+    calls back the interpreter.  Used temporarily: a fully compiled
+    version of the code may end up replacing it.
+    """
+    # 'redboxes' is only used to know the types of red arguments.
+    inputargs = [box.clonebox() for box in redboxes]
+    loop_token = make_loop_token(len(inputargs), jitdriver_sd)
+    # 'nb_red_args' might be smaller than len(redboxes),
+    # because it doesn't include the virtualizable boxes.
+    nb_red_args = jitdriver_sd.num_red_args
+    k = jitdriver_sd.portal_runner_adr
+    funcbox = history.ConstInt(heaptracker.adr2int(k))
+    callargs = [funcbox] + greenboxes + inputargs[:nb_red_args]
+    #
+    result_type = jitdriver_sd.result_type
+    if result_type == history.INT:
+        result = BoxInt()
+    elif result_type == history.REF:
+        result = BoxPtr()
+    elif result_type == history.FLOAT:
+        result = BoxFloat()
+    elif result_type == history.VOID:
+        result = None
+    else:
+        assert 0, "bad result_type"
+    if result is not None:
+        finishargs = [result]
+    else:
+        finishargs = []
+    #
+    jd = jitdriver_sd
+    faildescr = propagate_exception_descr
+    operations = [
+        ResOperation(rop.CALL, callargs, result, descr=jd.portal_calldescr),
+        ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=faildescr),
+        ResOperation(rop.FINISH, finishargs, None, descr=jd.portal_finishtoken)
+        ]
+    operations[1].fail_args = []
+    cpu.compile_loop(inputargs, operations, loop_token)
+    return loop_token

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/jitdriver.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/jitdriver.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/jitdriver.py	Tue Sep 14 16:34:16 2010
@@ -8,11 +8,14 @@
     #    self.portal_graph      ... pypy.jit.metainterp.warmspot
     #    self.portal_runner_ptr ... pypy.jit.metainterp.warmspot
     #    self.portal_runner_adr ... pypy.jit.metainterp.warmspot
+    #    self.portal_calldescr  ... pypy.jit.metainterp.warmspot
     #    self.num_green_args    ... pypy.jit.metainterp.warmspot
+    #    self.num_red_args      ... pypy.jit.metainterp.warmspot
     #    self.result_type       ... pypy.jit.metainterp.warmspot
     #    self.virtualizable_info... pypy.jit.metainterp.warmspot
     #    self.warmstate         ... pypy.jit.metainterp.warmspot
     #    self.handle_jitexc_from_bh pypy.jit.metainterp.warmspot
+    #    self.portal_finishtoken... pypy.jit.metainterp.pyjitpl
     #    self.index             ... pypy.jit.codewriter.call
     #    self.mainjitcode       ... pypy.jit.codewriter.call
 
@@ -20,6 +23,7 @@
     #    self.assembler_helper_adr
     #    self.index_of_virtualizable
     #    self.vable_token_descr
+    #    self.portal_calldescr
 
     # warmspot sets extra attributes starting with '_' for its own use.
 

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	Tue Sep 14 16:34:16 2010
@@ -690,25 +690,27 @@
         targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
         allboxes = greenboxes + redboxes
         warmrunnerstate = targetjitdriver_sd.warmstate
-        token = None
+        assembler_call = False
         if warmrunnerstate.inlining:
             if warmrunnerstate.can_inline_callable(greenboxes):
                 portal_code = targetjitdriver_sd.mainjitcode
                 return self.metainterp.perform_call(portal_code, allboxes,
                                                     greenkey=greenboxes)
-            token = warmrunnerstate.get_assembler_token(greenboxes)
+            assembler_call = True
             # verify that we have all green args, needed to make sure
             # that assembler that we call is still correct
             self.verify_green_args(targetjitdriver_sd, greenboxes)
         #
-        return self.do_recursive_call(targetjitdriver_sd, allboxes, token)
+        return self.do_recursive_call(targetjitdriver_sd, allboxes,
+                                      assembler_call)
 
-    def do_recursive_call(self, targetjitdriver_sd, allboxes, token=None):
+    def do_recursive_call(self, targetjitdriver_sd, allboxes,
+                          assembler_call=False):
         portal_code = targetjitdriver_sd.mainjitcode
         k = targetjitdriver_sd.portal_runner_adr
         funcbox = ConstInt(heaptracker.adr2int(k))
-        return self.do_residual_call(funcbox, portal_code.calldescr,
-                                     allboxes, assembler_call_token=token,
+        return self.do_residual_call(funcbox, portal_code.calldescr, allboxes,
+                                     assembler_call=assembler_call,
                                      assembler_call_jd=targetjitdriver_sd)
 
     opimpl_recursive_call_i = _opimpl_recursive_call
@@ -828,8 +830,6 @@
             self.metainterp.reached_loop_header(greenboxes, redboxes)
             self.pc = saved_pc
         else:
-            warmrunnerstate = jitdriver_sd.warmstate
-            token = warmrunnerstate.get_assembler_token(greenboxes)
             # warning! careful here.  We have to return from the current
             # frame containing the jit_merge_point, and then use
             # do_recursive_call() to follow the recursive call.  This is
@@ -843,7 +843,8 @@
             except ChangeFrame:
                 pass
             frame = self.metainterp.framestack[-1]
-            frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, token)
+            frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes,
+                                    assembler_call=True)
             raise ChangeFrame
 
     def debug_merge_point(self, jitdriver_sd, greenkey):
@@ -1058,7 +1059,7 @@
         return resbox
 
     def do_residual_call(self, funcbox, descr, argboxes,
-                         assembler_call_token=None,
+                         assembler_call=False,
                          assembler_call_jd=None):
         # First build allboxes: it may need some reordering from the
         # list provided in argboxes, depending on the order in which
@@ -1096,16 +1097,15 @@
         if (effectinfo is None or
                 effectinfo.extraeffect ==
                              effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE or
-                assembler_call_token is not None):
+                assembler_call):
             # residual calls require attention to keep virtualizables in-sync
             self.metainterp.clear_exception()
             self.metainterp.vable_and_vrefs_before_residual_call()
             resbox = self.metainterp.execute_and_record_varargs(
                 rop.CALL_MAY_FORCE, allboxes, descr=descr)
             self.metainterp.vrefs_after_residual_call()
-            if assembler_call_token is not None:
-                self.metainterp.direct_assembler_call(assembler_call_token,
-                                                      assembler_call_jd)
+            if assembler_call:
+                self.metainterp.direct_assembler_call(assembler_call_jd)
             if resbox is not None:
                 self.make_result_of_lastop(resbox)
             self.metainterp.vable_after_residual_call()
@@ -1217,6 +1217,7 @@
                     history.FLOAT: 'float',
                     history.VOID: 'void'}[jd.result_type]
             tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name)
+            jd.portal_finishtoken = tokens[0].finishdescr
             num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
             setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num)
         #
@@ -2103,20 +2104,24 @@
         op.args = [resbox_as_const] + op.args
         return resbox
 
-    def direct_assembler_call(self, token, targetjitdriver_sd):
+    def direct_assembler_call(self, targetjitdriver_sd):
         """ Generate a direct call to assembler for portal entry point,
         patching the CALL_MAY_FORCE that occurred just now.
         """
         op = self.history.operations.pop()
         assert op.opnum == rop.CALL_MAY_FORCE
         num_green_args = targetjitdriver_sd.num_green_args
-        args = op.args[num_green_args + 1:]
+        greenargs = op.args[1:num_green_args+1]
+        args = op.args[num_green_args+1:]
+        assert len(args) == targetjitdriver_sd.num_red_args
         vinfo = targetjitdriver_sd.virtualizable_info
         if vinfo is not None:
             index = targetjitdriver_sd.index_of_virtualizable
             vbox = args[index]
             args = args + self.gen_load_from_other_virtualizable(vinfo, vbox)
             # ^^^ and not "+=", which makes 'args' a resizable list
+        warmrunnerstate = targetjitdriver_sd.warmstate
+        token = warmrunnerstate.get_assembler_token(greenargs, args)
         op.opnum = rop.CALL_ASSEMBLER
         op.args = args
         op.descr = token

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py	Tue Sep 14 16:34:16 2010
@@ -455,6 +455,31 @@
         # the CALL_PURE is constant-folded away by optimizeopt.py
         self.check_loops(int_sub=1, call=0, call_pure=0)
 
+    def test_pure_function_returning_object(self):
+        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
+        class V:
+            def __init__(self, x):
+                self.x = x
+        v1 = V(1)
+        v2 = V(2)
+        def externfn(x):
+            if x:
+                return v1
+            else:
+                return v2
+        externfn._pure_function_ = True
+        def f(n, m):
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n, m=m)
+                myjitdriver.jit_merge_point(n=n, m=m)
+                m = V(m).x
+                n -= externfn(m).x + externfn(m + m - m).x
+            return n
+        res = self.meta_interp(f, [21, 5])
+        assert res == -1
+        # the CALL_PURE is constant-folded away by optimizeopt.py
+        self.check_loops(int_sub=1, call=0, call_pure=0, getfield_gc=1)
+
     def test_constant_across_mp(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
         class X(object):
@@ -530,6 +555,32 @@
         assert res == -2
         self.check_loop_count(1)
 
+    def test_can_never_inline(self):
+        def can_never_inline(x):
+            return x > 50
+        myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
+                                can_never_inline = can_never_inline)
+        @dont_look_inside
+        def marker():
+            pass
+        def f(x, y):
+            while y >= 0:
+                myjitdriver.can_enter_jit(x=x, y=y)
+                myjitdriver.jit_merge_point(x=x, y=y)
+                x += 1
+                if x == 4 or x == 61:
+                    marker()
+                y -= x
+            return y
+        #
+        res = self.meta_interp(f, [3, 6], repeat=7)
+        assert res == 6 - 4 - 5
+        self.check_history(call=0)   # because the trace starts in the middle
+        #
+        res = self.meta_interp(f, [60, 84], repeat=7)
+        assert res == 84 - 61 - 62
+        self.check_history(call=1)   # because the trace starts immediately
+
     def test_format(self):
         def f(n):
             return len("<%d>" % n)

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	Tue Sep 14 16:34:16 2010
@@ -1,10 +1,11 @@
 from pypy.jit.metainterp.history import LoopToken, ConstInt, History, Stats
-from pypy.jit.metainterp.history import BoxInt
+from pypy.jit.metainterp.history import BoxInt, INT
 from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode
 from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop
 from pypy.jit.metainterp.compile import ResumeGuardDescr
 from pypy.jit.metainterp.compile import ResumeGuardCountersInt
-from pypy.jit.metainterp import optimize, jitprof, typesystem
+from pypy.jit.metainterp.compile import compile_tmp_callback
+from pypy.jit.metainterp import optimize, jitprof, typesystem, compile
 from pypy.jit.metainterp.test.oparser import parse
 from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin
 
@@ -154,3 +155,67 @@
     count = rgc.see_int(192)
     assert count == 1
     assert rgc.counters == [1, 1, 7, 6, 1]
+
+
+def test_compile_tmp_callback():
+    from pypy.jit.codewriter import heaptracker
+    from pypy.jit.backend.llgraph import runner
+    from pypy.rpython.lltypesystem import lltype, llmemory
+    from pypy.rpython.annlowlevel import llhelper
+    from pypy.rpython.llinterp import LLException
+    #
+    cpu = runner.LLtypeCPU(None)
+    FUNC = lltype.FuncType([lltype.Signed]*4, lltype.Signed)
+    def ll_portal_runner(g1, g2, r3, r4):
+        assert (g1, g2, r3, r4) == (12, 34, -156, -178)
+        if raiseme:
+            raise raiseme
+        else:
+            return 54321
+    #
+    class FakeJitDriverSD:
+        portal_runner_ptr = llhelper(lltype.Ptr(FUNC), ll_portal_runner)
+        portal_runner_adr = llmemory.cast_ptr_to_adr(portal_runner_ptr)
+        portal_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+        portal_finishtoken = compile.DoneWithThisFrameDescrInt()
+        num_red_args = 2
+        result_type = INT
+    #
+    loop_token = compile_tmp_callback(cpu, FakeJitDriverSD(),
+                                      [ConstInt(12), ConstInt(34)],
+                                      [BoxInt(56), ConstInt(78), BoxInt(90)])
+    #
+    raiseme = None
+    cpu.set_future_value_int(0, -156)
+    cpu.set_future_value_int(1, -178)
+    cpu.set_future_value_int(2, -190)     # passed in, but dropped
+    fail_descr = cpu.execute_token(loop_token)
+    assert fail_descr is FakeJitDriverSD().portal_finishtoken
+    #
+    EXC = lltype.GcStruct('EXC')
+    llexc = lltype.malloc(EXC)
+    raiseme = LLException("exception class", llexc)
+    cpu.set_future_value_int(0, -156)
+    cpu.set_future_value_int(1, -178)
+    cpu.set_future_value_int(2, -190)
+    fail_descr = cpu.execute_token(loop_token)
+    assert isinstance(fail_descr, compile.PropagateExceptionDescr)
+    got = cpu.grab_exc_value()
+    assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), got) == llexc
+    #
+    class FakeMetaInterpSD:
+        class ExitFrameWithExceptionRef(Exception):
+            pass
+    FakeMetaInterpSD.cpu = cpu
+    class FakeJitDriverSD:
+        pass
+    cpu.set_future_value_int(0, -156)
+    cpu.set_future_value_int(1, -178)
+    cpu.set_future_value_int(2, -190)
+    fail_descr = cpu.execute_token(loop_token)
+    try:
+        fail_descr.handle_fail(FakeMetaInterpSD(), FakeJitDriverSD())
+    except FakeMetaInterpSD.ExitFrameWithExceptionRef, e:
+        assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), e.args[1]) == llexc
+    else:
+        assert 0, "should have raised"

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	Tue Sep 14 16:34:16 2010
@@ -4,7 +4,8 @@
                                                             #OOtypeMixin,
                                                             BaseTest)
 from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder
-from pypy.jit.metainterp import optimizeopt
+import pypy.jit.metainterp.optimizeopt.optimizer as optimizeopt
+import pypy.jit.metainterp.optimizeopt.virtualize as virtualize
 from pypy.jit.metainterp.optimizeopt import optimize_loop_1
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
 from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
@@ -64,7 +65,7 @@
         class cpu(object):
             pass
     opt = FakeOptimizer()
-    virt1 = optimizeopt.AbstractVirtualStructValue(opt, None)
+    virt1 = virtualize.AbstractVirtualStructValue(opt, None)
     lst1 = virt1._get_field_descr_list()
     assert lst1 == []
     lst2 = virt1._get_field_descr_list()
@@ -75,7 +76,7 @@
     lst4 = virt1._get_field_descr_list()
     assert lst3 is lst4
     
-    virt2 = optimizeopt.AbstractVirtualStructValue(opt, None)
+    virt2 = virtualize.AbstractVirtualStructValue(opt, None)
     lst5 = virt2._get_field_descr_list()
     assert lst5 is lst1
     virt2.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
@@ -88,7 +89,7 @@
             self.fieldnums = fieldnums
         def equals(self, fieldnums):
             return self.fieldnums == fieldnums
-    class FakeVirtualValue(optimizeopt.AbstractVirtualValue):
+    class FakeVirtualValue(virtualize.AbstractVirtualValue):
         def _make_virtual(self, *args):
             return FakeVInfo()
     v1 = FakeVirtualValue(None, None, None)
@@ -257,6 +258,7 @@
         optimize_loop_1(metainterp_sd, loop)
         #
         expected = self.parse(optops)
+        print '\n'.join([str(o) for o in loop.operations])
         self.assert_equal(loop, expected)
 
     def test_simple(self):
@@ -266,7 +268,13 @@
         guard_value(i0, 0) [i0]
         jump(i)
         """
-        self.optimize_loop(ops, 'Not', ops)
+        expected = """
+        [i]
+        i0 = int_sub(i, 1)
+        guard_value(i0, 0) [i0]
+        jump(1)
+        """
+        self.optimize_loop(ops, 'Not', expected)
 
     def test_constant_propagate(self):
         ops = """
@@ -680,7 +688,13 @@
         guard_value(i1, 0) [i]
         jump(i)
         """
-        self.optimize_loop(ops, 'Not', ops)
+        expected = """
+        [i]
+        i1 = int_add(i, 3)
+        guard_value(i1, 0) [i]
+        jump(-3)
+        """
+        self.optimize_loop(ops, 'Not', expected)
 
     def test_int_is_true_of_bool(self):
         ops = """
@@ -3089,6 +3103,724 @@
         '''
         self.optimize_loop(ops, 'Not', expected)
 
+    def test_bound_lt(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_lt(i0, 5)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_noguard(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        i2 = int_lt(i0, 5)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        i2 = int_lt(i0, 5)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_noopt(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_false(i1) []
+        i2 = int_lt(i0, 5)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_false(i1) []
+        i2 = int_lt(i0, 5)
+        guard_true(i2) []
+        jump(4)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_rev(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_false(i1) []
+        i2 = int_gt(i0, 3)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_false(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_tripple(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 0)
+        guard_true(i1) []
+        i2 = int_lt(i0, 7)
+        guard_true(i2) []
+        i3 = int_lt(i0, 5)
+        guard_true(i3) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 0)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_add(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add(i0, 10)
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add(i0, 10)        
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_add_before(self):
+        ops = """
+        [i0]
+        i2 = int_add(i0, 10)
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        i1 = int_lt(i0, 6)
+        guard_true(i1) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i2 = int_add(i0, 10)
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_add_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add(i0, 10)        
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_add_ovf_before(self):
+        ops = """
+        [i0]
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        i1 = int_lt(i0, 6)
+        guard_true(i1) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_sub(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_sub(i0, 10)
+        i3 = int_lt(i2, -5)
+        guard_true(i3) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_sub(i0, 10)        
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_sub_before(self):
+        ops = """
+        [i0]
+        i2 = int_sub(i0, 10)
+        i3 = int_lt(i2, -5)
+        guard_true(i3) []
+        i1 = int_lt(i0, 5)
+        guard_true(i1) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i2 = int_sub(i0, 10)
+        i3 = int_lt(i2, -5)
+        guard_true(i3) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_ltle(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_le(i0, 3)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_lelt(self):
+        ops = """
+        [i0]
+        i1 = int_le(i0, 4)
+        guard_true(i1) []
+        i2 = int_lt(i0, 5)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_le(i0, 4)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_gt(self):
+        ops = """
+        [i0]
+        i1 = int_gt(i0, 5)
+        guard_true(i1) []
+        i2 = int_gt(i0, 4)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_gt(i0, 5)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_gtge(self):
+        ops = """
+        [i0]
+        i1 = int_gt(i0, 5)
+        guard_true(i1) []
+        i2 = int_ge(i0, 6)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_gt(i0, 5)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_gegt(self):
+        ops = """
+        [i0]
+        i1 = int_ge(i0, 5)
+        guard_true(i1) []
+        i2 = int_gt(i0, 4)
+        guard_true(i2) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_ge(i0, 5)
+        guard_true(i1) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_ge(i0, 0)
+        guard_true(i1) []
+        i2 = int_lt(i0, 10)
+        guard_true(i2) []
+        i3 = int_add_ovf(i0, 1)
+        guard_no_overflow() []
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i1 = int_ge(i0, 0)
+        guard_true(i1) []
+        i2 = int_lt(i0, 10)
+        guard_true(i2) []
+        i3 = int_add(i0, 1)
+        jump(i3)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_addsub_const(self):
+        ops = """
+        [i0]
+        i1 = int_add(i0, 1)
+        i2 = int_sub(i1, 1)
+        i3 = int_add(i2, 1)
+        i4 = int_mul(i2, i3)
+        jump(i4)
+        """
+        expected = """
+        [i0]
+        i1 = int_add(i0, 1)
+        i4 = int_mul(i0, i1)
+        jump(i4)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_addsub_int(self):
+        ops = """
+        [i0, i10]
+        i1 = int_add(i0, i10)
+        i2 = int_sub(i1, i10)
+        i3 = int_add(i2, i10)
+        i4 = int_add(i2, i3)
+        jump(i4, i10)
+        """
+        expected = """
+        [i0, i10]
+        i1 = int_add(i0, i10)
+        i4 = int_add(i0, i1)
+        jump(i4, i10)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_addsub_int2(self):
+        ops = """
+        [i0, i10]
+        i1 = int_add(i10, i0)
+        i2 = int_sub(i1, i10)
+        i3 = int_add(i10, i2)
+        i4 = int_add(i2, i3)
+        jump(i4, i10)
+        """
+        expected = """
+        [i0, i10]
+        i1 = int_add(i10, i0)
+        i4 = int_add(i0, i1)
+        jump(i4, i10)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_framestackdepth_overhead(self):
+        ops = """
+        [p0, i22]
+        i1 = getfield_gc(p0, descr=valuedescr)
+        i2 = int_gt(i1, i22)
+        guard_false(i2) []
+        i3 = int_add(i1, 1)
+        setfield_gc(p0, i3, descr=valuedescr)
+        i4 = int_sub(i3, 1)
+        setfield_gc(p0, i4, descr=valuedescr)
+        i5 = int_gt(i4, i22)
+        guard_false(i5) []
+        i6 = int_add(i4, 1)
+        i331 = force_token()
+        i7 = int_sub(i6, 1)
+        setfield_gc(p0, i7, descr=valuedescr)
+        jump(p0, i22)
+        """
+        expected = """
+        [p0, i22]
+        i1 = getfield_gc(p0, descr=valuedescr)
+        i2 = int_gt(i1, i22)
+        guard_false(i2) []
+        i3 = int_add(i1, 1)
+        i331 = force_token()
+        setfield_gc(p0, i1, descr=valuedescr)
+        jump(p0, i22)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_addsub_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_sub_ovf(i1, 5)
+        guard_no_overflow() []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_sub(i1, 5)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_subadd_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_sub_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_add_ovf(i1, 5)
+        guard_no_overflow() []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_sub_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_add(i1, 5)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_and(self):
+        ops = """
+        [i0]
+        i1 = int_and(i0, 255)
+        i2 = int_lt(i1, 500)
+        guard_true(i2) []
+        i3 = int_le(i1, 255)
+        guard_true(i3) []
+        i4 = int_gt(i1, -1)
+        guard_true(i4) []
+        i5 = int_ge(i1, 0)
+        guard_true(i5) []
+        i6 = int_lt(i1, 0)
+        guard_false(i6) []
+        i7 = int_le(i1, -1)
+        guard_false(i7) []
+        i8 = int_gt(i1, 255)
+        guard_false(i8) []
+        i9 = int_ge(i1, 500)
+        guard_false(i9) []
+        i12 = int_lt(i1, 100)
+        guard_true(i12) []
+        i13 = int_le(i1, 90)
+        guard_true(i13) []
+        i14 = int_gt(i1, 10)
+        guard_true(i14) []
+        i15 = int_ge(i1, 20)
+        guard_true(i15) []        
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        i1 = int_and(i0, 255)
+        i12 = int_lt(i1, 100)
+        guard_true(i12) []
+        i13 = int_le(i1, 90)
+        guard_true(i13) []
+        i14 = int_gt(i1, 10)
+        guard_true(i14) []
+        i15 = int_ge(i1, 20)
+        guard_true(i15) []        
+        jump(i1)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_subsub_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i2 = int_gt(i1, 1)
+        guard_true(i2) []
+        i3 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i4 = int_gt(i3, 1)
+        guard_true(i4) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i2 = int_gt(i1, 1)
+        guard_true(i2) []
+        i3 = int_sub(1, i0)
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_eq(self):
+        ops = """
+        [i0, i1]
+        i2 = int_le(i0, 4)
+        guard_true(i2) []
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+        i4 = int_lt(i1, 5)
+        guard_true(i4) []
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        i2 = int_le(i0, 4)
+        guard_true(i2) []
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_bound_eq_const(self):
+        ops = """
+        [i0]
+        i1 = int_eq(i0, 7)
+        guard_true(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_eq(i0, 7)
+        guard_true(i1) []
+        jump(10)
+
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_eq_const_not(self):
+        ops = """
+        [i0]
+        i1 = int_eq(i0, 7)
+        guard_false(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_eq(i0, 7)
+        guard_false(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_ne_const(self):
+        ops = """
+        [i0]
+        i1 = int_ne(i0, 7)
+        guard_false(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_ne(i0, 7)
+        guard_false(i1) []
+        jump(10)
+
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_ne_const_not(self):
+        ops = """
+        [i0]
+        i1 = int_ne(i0, 7)
+        guard_true(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_ne(i0, 7)
+        guard_true(i1) []
+        i2 = int_add(i0, 3)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_ltne(self):
+        ops = """
+        [i0, i1]
+        i2 = int_lt(i0, 7)
+        guard_true(i2) []
+        i3 = int_ne(i0, 10)
+        guard_true(i2) []
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        i2 = int_lt(i0, 7)
+        guard_true(i2) []
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_bound_lege_const(self):
+        ops = """
+        [i0]
+        i1 = int_ge(i0, 7)
+        guard_true(i1) []
+        i2 = int_le(i0, 7)
+        guard_true(i2) []
+        i3 = int_add(i0, 3)
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i1 = int_ge(i0, 7)
+        guard_true(i1) []
+        i2 = int_le(i0, 7)
+        guard_true(i2) []
+        jump(10)
+
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_mul_ovf(self):
+        ops = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i3 = int_lt(i1, 5)
+        guard_true(i3) []
+        i4 = int_gt(i1, -10)
+        guard_true(i4) []
+        i5 = int_mul_ovf(i2, i1)
+        guard_no_overflow() []
+        i6 = int_lt(i5, -2550)
+        guard_false(i6) []
+        i7 = int_ge(i5, 1276)
+        guard_false(i7) []
+        i8 = int_gt(i5, 126)
+        guard_true(i8) []
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i3 = int_lt(i1, 5)
+        guard_true(i3) []
+        i4 = int_gt(i1, -10)
+        guard_true(i4) []
+        i5 = int_mul(i2, i1)
+        i8 = int_gt(i5, 126)
+        guard_true(i8) []
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_mul_ovf_before(self):
+        ops = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i22 = int_add(i2, 1)
+        i3 = int_mul_ovf(i22, i1)
+        guard_no_overflow() []
+        i4 = int_lt(i3, 10)
+        guard_true(i4) []
+        i5 = int_gt(i3, 2)
+        guard_true(i5) []
+        i6 = int_lt(i1, 0)
+        guard_false(i6) []
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i22 = int_add(i2, 1)
+        i3 = int_mul_ovf(i22, i1)
+        guard_no_overflow() []
+        i4 = int_lt(i3, 10)
+        guard_true(i4) []
+        i5 = int_gt(i3, 2)
+        guard_true(i5) []
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_sub_ovf_before(self):
+        ops = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i3 = int_sub_ovf(i2, i1)
+        guard_no_overflow() []
+        i4 = int_le(i3, 10)
+        guard_true(i4) []
+        i5 = int_ge(i3, 2)
+        guard_true(i5) []
+        i6 = int_lt(i1, -10)
+        guard_false(i6) []
+        i7 = int_gt(i1, 253)
+        guard_false(i7) []
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        i2 = int_and(i0, 255)
+        i3 = int_sub_ovf(i2, i1)
+        guard_no_overflow() []
+        i4 = int_le(i3, 10)
+        guard_true(i4) []
+        i5 = int_ge(i3, 2)
+        guard_true(i5) []
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+        
+
+
 ##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
 
 ##    def test_instanceof(self):

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py	Tue Sep 14 16:34:16 2010
@@ -612,9 +612,88 @@
                 driver.can_enter_jit(codeno=codeno, i=i, j=j)
 
         portal(2, 50)
-        self.meta_interp(portal, [2, 20], inline=True)
-        self.check_loops(call_assembler=0, call_may_force=1,
-                         everywhere=True)
+
+        from pypy.jit.metainterp import compile, pyjitpl
+        pyjitpl._warmrunnerdesc = None
+        trace = []
+        def my_ctc(*args):
+            looptoken = original_ctc(*args)
+            trace.append(looptoken)
+            return looptoken
+        original_ctc = compile.compile_tmp_callback
+        try:
+            compile.compile_tmp_callback = my_ctc
+            self.meta_interp(portal, [2, 20], inline=True)
+            self.check_loops(call_assembler=1, call_may_force=0,
+                             everywhere=True)
+        finally:
+            compile.compile_tmp_callback = original_ctc
+        # check that we made a temporary callback
+        assert len(trace) == 1
+        # and that we later redirected it to something else
+        try:
+            redirected = pyjitpl._warmrunnerdesc.cpu._redirected_call_assembler
+        except AttributeError:
+            pass    # not the llgraph backend
+        else:
+            print redirected
+            assert redirected.keys() == trace
+
+    def test_recursion_cant_call_assembler_directly_with_virtualizable(self):
+        # exactly the same logic as the previous test, but with 'frame.j'
+        # instead of just 'j'
+        class Frame(object):
+            _virtualizable2_ = ['j']
+            def __init__(self, j):
+                self.j = j
+
+        driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'],
+                           virtualizables = ['frame'],
+                           get_printable_location = lambda codeno : str(codeno))
+
+        def portal(codeno, frame):
+            i = 0
+            while 1:
+                driver.jit_merge_point(codeno=codeno, i=i, frame=frame)
+                if i == 1:
+                    if frame.j == 0:
+                        return
+                    portal(2, Frame(frame.j - 1))
+                elif i == 3:
+                    return
+                i += 1
+                driver.can_enter_jit(codeno=codeno, i=i, frame=frame)
+
+        def main(codeno, j):
+            portal(codeno, Frame(j))
+
+        main(2, 50)
+
+        from pypy.jit.metainterp import compile, pyjitpl
+        pyjitpl._warmrunnerdesc = None
+        trace = []
+        def my_ctc(*args):
+            looptoken = original_ctc(*args)
+            trace.append(looptoken)
+            return looptoken
+        original_ctc = compile.compile_tmp_callback
+        try:
+            compile.compile_tmp_callback = my_ctc
+            self.meta_interp(main, [2, 20], inline=True)
+            self.check_loops(call_assembler=1, call_may_force=0,
+                             everywhere=True)
+        finally:
+            compile.compile_tmp_callback = original_ctc
+        # check that we made a temporary callback
+        assert len(trace) == 1
+        # and that we later redirected it to something else
+        try:
+            redirected = pyjitpl._warmrunnerdesc.cpu._redirected_call_assembler
+        except AttributeError:
+            pass    # not the llgraph backend
+        else:
+            print redirected
+            assert redirected.keys() == trace
 
     def test_directly_call_assembler_return(self):
         driver = JitDriver(greens = ['codeno'], reds = ['i', 'k'],

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py	Tue Sep 14 16:34:16 2010
@@ -1,7 +1,7 @@
 import py
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue
-from pypy.jit.metainterp.optimizeopt import VStructValue
+from pypy.jit.metainterp.optimizeopt.virtualize import VirtualValue, OptValue, VArrayValue
+from pypy.jit.metainterp.optimizeopt.virtualize import VStructValue
 from pypy.jit.metainterp.resume import *
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt
 from pypy.jit.metainterp.history import ConstPtr, ConstFloat

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py	Tue Sep 14 16:34:16 2010
@@ -162,13 +162,16 @@
     assert cell1.entry_loop_token == "entry loop token"
 
 def test_make_jitdriver_callbacks_1():
+    class FakeWarmRunnerDesc:
+        cpu = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = None
         _confirm_enter_jit_ptr = None
+        _can_never_inline_ptr = None
     class FakeCell:
         dont_trace_here = False
-    state = WarmEnterState(None, FakeJitDriverSD())
+    state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     def jit_getter(build, *args):
         return FakeCell()
     state.jit_getter = jit_getter
@@ -185,10 +188,12 @@
                                               lltype.Ptr(rstr.STR)))
     class FakeWarmRunnerDesc:
         rtyper = None
+        cpu = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = llhelper(GET_LOCATION, get_location)
         _confirm_enter_jit_ptr = None
+        _can_never_inline_ptr = None
         _get_jitcell_at_ptr = None
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     state.make_jitdriver_callbacks()
@@ -205,13 +210,37 @@
                                             lltype.Signed], lltype.Bool))
     class FakeWarmRunnerDesc:
         rtyper = None
+        cpu = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = None
         _confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit)
+        _can_never_inline_ptr = None
         _get_jitcell_at_ptr = None
 
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     state.make_jitdriver_callbacks()
     res = state.confirm_enter_jit(5, 42.5, 3)
     assert res is True
+
+def test_make_jitdriver_callbacks_5():
+    def can_never_inline(x, y):
+        assert x == 5
+        assert y == 42.5
+        return True
+    CAN_NEVER_INLINE = lltype.Ptr(lltype.FuncType(
+        [lltype.Signed, lltype.Float], lltype.Bool))
+    class FakeWarmRunnerDesc:
+        rtyper = None
+        cpu = None
+    class FakeJitDriverSD:
+        _green_args_spec = [lltype.Signed, lltype.Float]
+        _get_printable_location_ptr = None
+        _confirm_enter_jit_ptr = None
+        _can_never_inline_ptr = llhelper(CAN_NEVER_INLINE, can_never_inline)
+        _get_jitcell_at_ptr = None
+
+    state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
+    state.make_jitdriver_callbacks()
+    res = state.can_never_inline(5, 42.5)
+    assert res is True

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	Tue Sep 14 16:34:16 2010
@@ -425,6 +425,8 @@
             jd._confirm_enter_jit_ptr = self._make_hook_graph(jd,
                 annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool,
                 onlygreens=False)
+            jd._can_never_inline_ptr = self._make_hook_graph(jd,
+                annhelper, jd.jitdriver.can_never_inline, annmodel.s_Bool)
         annhelper.finish()
 
     def _make_hook_graph(self, jitdriver_sd, annhelper, func,
@@ -455,6 +457,7 @@
         jd._green_args_spec = [v.concretetype for v in greens_v]
         jd._red_args_types = [history.getkind(v.concretetype) for v in reds_v]
         jd.num_green_args = len(jd._green_args_spec)
+        jd.num_red_args = len(jd._red_args_types)
         RESTYPE = graph.getreturnvar().concretetype
         (jd._JIT_ENTER_FUNCTYPE,
          jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
@@ -582,9 +585,11 @@
         ts = self.cpu.ts
 
         def ll_portal_runner(*args):
+            start = True
             while 1:
                 try:
-                    jd._maybe_enter_from_start_fn(*args)
+                    if start:
+                        jd._maybe_enter_from_start_fn(*args)
                     return support.maybe_on_top_of_llinterp(rtyper,
                                                       portal_ptr)(*args)
                 except self.ContinueRunningNormally, e:
@@ -593,6 +598,8 @@
                         x = getattr(e, attrname)[count]
                         x = specialize_value(ARGTYPE, x)
                         args = args + (x,)
+                    start = False
+                    continue
                 except self.DoneWithThisFrameVoid:
                     assert result_kind == 'void'
                     return
@@ -648,7 +655,7 @@
         jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE,
                                                 ll_portal_runner)
         jd.portal_runner_adr = llmemory.cast_ptr_to_adr(jd.portal_runner_ptr)
-        self.cpu.portal_calldescr = self.cpu.calldescrof(
+        jd.portal_calldescr = self.cpu.calldescrof(
             jd._PTR_PORTAL_FUNCTYPE.TO,
             jd._PTR_PORTAL_FUNCTYPE.TO.ARGS,
             jd._PTR_PORTAL_FUNCTYPE.TO.RESULT)

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py	Tue Sep 14 16:34:16 2010
@@ -211,7 +211,11 @@
                                               entry_loop_token):
         cell = self.jit_cell_at_key(greenkey)
         cell.counter = -1
+        old_token = cell.entry_loop_token
         cell.entry_loop_token = entry_loop_token
+        if old_token is not None:
+            cpu = self.warmrunnerdesc.cpu
+            cpu.redirect_call_assembler(old_token, entry_loop_token)
 
     # ----------
 
@@ -491,8 +495,12 @@
         #
         unwrap_greenkey = self.make_unwrap_greenkey()
         jit_getter = self.make_jitcell_getter()
+        jd = self.jitdriver_sd
+        cpu = self.warmrunnerdesc.cpu
 
         def can_inline_greenargs(*greenargs):
+            if can_never_inline(*greenargs):
+                return False
             cell = jit_getter(False, *greenargs)
             if cell is not None and cell.dont_trace_here:
                 return False
@@ -503,11 +511,13 @@
         self.can_inline_greenargs = can_inline_greenargs
         self.can_inline_callable = can_inline_callable
 
-        def get_assembler_token(greenkey):
-            greenargs = unwrap_greenkey(greenkey)
-            cell = jit_getter(False, *greenargs)
-            if cell is None or cell.counter >= 0:
-                return None
+        def get_assembler_token(greenkey, redboxes):
+            # 'redboxes' is only used to know the types of red arguments
+            cell = self.jit_cell_at_key(greenkey)
+            if cell.entry_loop_token is None:
+                from pypy.jit.metainterp.compile import compile_tmp_callback
+                cell.entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
+                                                             redboxes)
             return cell.entry_loop_token
         self.get_assembler_token = get_assembler_token
         
@@ -546,3 +556,16 @@
                                                       confirm_enter_jit_ptr)
                 return fn(*args)
         self.confirm_enter_jit = confirm_enter_jit
+        #
+        can_never_inline_ptr = self.jitdriver_sd._can_never_inline_ptr
+        if can_never_inline_ptr is None:
+            def can_never_inline(*greenargs):
+                return False
+        else:
+            rtyper = self.warmrunnerdesc.rtyper
+            #
+            def can_never_inline(*greenargs):
+                fn = support.maybe_on_top_of_llinterp(rtyper,
+                                                      can_never_inline_ptr)
+                return fn(*greenargs)
+        self.can_never_inline = can_never_inline

Modified: pypy/branch/fast-forward/pypy/jit/tool/traceviewer.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/tool/traceviewer.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/tool/traceviewer.py	Tue Sep 14 16:34:16 2010
@@ -250,13 +250,14 @@
 class Counts(dict):
     pass
 
-def main(loopfile, options, view=True):
+def main(loopfile, use_threshold, view=True):
     countname = py.path.local(loopfile + '.count')
     if countname.check():
-        counts = [line.rsplit(':', 1) for line in countname.readlines()]
-        counts = Counts([(k, int(v.strip('\n'))) for k, v in counts])
+        counts = [re.split(r' +', line, 1) for line in countname.readlines()]
+        counts = Counts([(k.strip("\n"), int(v.strip('\n')))
+                         for v, k in counts])
         l = list(sorted(counts.values()))
-        if len(l) > 20 and options.use_threshold:
+        if len(l) > 20 and use_threshold:
             counts.threshold = l[-20]
         else:
             counts.threshold = 0
@@ -274,7 +275,7 @@
 if __name__ == '__main__':
     parser = optparse.OptionParser(usage=__doc__)
     parser.add_option('--use-threshold', dest='use_threshold',
-                      action="store_true")
+                      action="store_true", default=False)
     options, args = parser.parse_args(sys.argv)
     if len(args) != 2:
         print __doc__

Modified: pypy/branch/fast-forward/pypy/module/_socket/interp_func.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_socket/interp_func.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_socket/interp_func.py	Tue Sep 14 16:34:16 2010
@@ -280,7 +280,7 @@
                             space.wrap(socktype),
                             space.wrap(protocol),
                             space.wrap(canonname),
-                            addr.as_object(space)])
+                            addr.as_object(-1, space)]) # -1 as per cpython
             for (family, socktype, protocol, canonname, addr) in lst]
     return space.newlist(lst1)
 getaddrinfo.unwrap_spec = [ObjSpace, W_Root, W_Root, int, int, int, int]

Modified: pypy/branch/fast-forward/pypy/module/_socket/interp_socket.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_socket/interp_socket.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_socket/interp_socket.py	Tue Sep 14 16:34:16 2010
@@ -24,7 +24,7 @@
         try:
             sock, addr = self.accept(W_RSocket)
             return space.newtuple([space.wrap(sock),
-                                   addr.as_object(space)])
+                                   addr.as_object(sock.fd, space)])
         except SocketError, e:
             raise converted_error(space, e)
     accept_w.unwrap_spec = ['self', ObjSpace]
@@ -109,7 +109,7 @@
         """
         try:
             addr = self.getpeername()
-            return addr.as_object(space)
+            return addr.as_object(self.fd, space)
         except SocketError, e:
             raise converted_error(space, e)
     getpeername_w.unwrap_spec = ['self', ObjSpace]
@@ -122,7 +122,7 @@
         """
         try:
             addr = self.getsockname()
-            return addr.as_object(space)
+            return addr.as_object(self.fd, space)
         except SocketError, e:
             raise converted_error(space, e)
     getsockname_w.unwrap_spec = ['self', ObjSpace]
@@ -202,7 +202,7 @@
         try:
             data, addr = self.recvfrom(buffersize, flags)
             if addr:
-                w_addr = addr.as_object(space)
+                w_addr = addr.as_object(self.fd, space)
             else:
                 w_addr = space.w_None
             return space.newtuple([space.wrap(data), w_addr])
@@ -330,7 +330,7 @@
         try:
             readlgt, addr = self.recvfrom_into(rwbuffer, nbytes, flags)
             if addr:
-                w_addr = addr.as_object(space)
+                w_addr = addr.as_object(self.fd, space)
             else:
                 w_addr = space.w_None
             return space.newtuple([space.wrap(readlgt), w_addr])

Modified: pypy/branch/fast-forward/pypy/module/_socket/test/test_sock_app.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_socket/test/test_sock_app.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_socket/test/test_sock_app.py	Tue Sep 14 16:34:16 2010
@@ -2,6 +2,8 @@
 import sys
 import py
 from pypy.tool.udir import udir
+from pypy.rlib import rsocket
+from pypy.rpython.lltypesystem import lltype, rffi
 
 def setup_module(mod):
     mod.space = gettestobjspace(usemodules=['_socket', 'array'])
@@ -221,21 +223,45 @@
                         "(_socket, host, port): return _socket.getaddrinfo(host, port)")
     assert space.unwrap(w_l) == info
 
-def test_unknown_addr_as_object():
-    from pypy.rlib import rsocket
-    from pypy.rpython.lltypesystem import lltype, rffi
-    
+def test_unknown_addr_as_object():    
     c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw')
     c_addr.c_sa_data[0] = 'c'
     rffi.setintfield(c_addr, 'c_sa_family', 15)
     # XXX what size to pass here? for the purpose of this test it has
     #     to be short enough so we have some data, 1 sounds good enough
     #     + sizeof USHORT
-    w_obj = rsocket.Address(c_addr, 1 + 2).as_object(space)
+    w_obj = rsocket.Address(c_addr, 1 + 2).as_object(-1, space)
     assert space.is_true(space.isinstance(w_obj, space.w_tuple))
     assert space.int_w(space.getitem(w_obj, space.wrap(0))) == 15
     assert space.str_w(space.getitem(w_obj, space.wrap(1))) == 'c'
 
+def test_addr_raw_packet():
+    if not hasattr(rsocket._c, 'sockaddr_ll'):
+        py.test.skip("posix specific test")
+    c_addr_ll = lltype.malloc(rsocket._c.sockaddr_ll, flavor='raw')
+    addrlen = rffi.sizeof(rsocket._c.sockaddr_ll)
+    c_addr = rffi.cast(lltype.Ptr(rsocket._c.sockaddr), c_addr_ll)
+    rffi.setintfield(c_addr_ll, 'c_sll_ifindex', 1)
+    rffi.setintfield(c_addr_ll, 'c_sll_protocol', 8)
+    rffi.setintfield(c_addr_ll, 'c_sll_pkttype', 13)
+    rffi.setintfield(c_addr_ll, 'c_sll_hatype', 0)
+    rffi.setintfield(c_addr_ll, 'c_sll_halen', 3)
+    c_addr_ll.c_sll_addr[0] = 'a'
+    c_addr_ll.c_sll_addr[1] = 'b'
+    c_addr_ll.c_sll_addr[2] = 'c'
+    rffi.setintfield(c_addr, 'c_sa_family', socket.AF_PACKET)
+    # fd needs to be somehow valid
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    fd = s.fileno()
+    w_obj = rsocket.make_address(c_addr, addrlen).as_object(fd, space)
+    assert space.is_true(space.eq(w_obj, space.newtuple([
+        space.wrap('lo'),
+        space.wrap(socket.ntohs(8)),
+        space.wrap(13),
+        space.wrap(False),
+        space.wrap("abc"),
+        ])))
+
 def test_getnameinfo():
     host = "127.0.0.1"
     port = 25

Modified: pypy/branch/fast-forward/pypy/module/_ssl/interp_ssl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_ssl/interp_ssl.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_ssl/interp_ssl.py	Tue Sep 14 16:34:16 2010
@@ -18,6 +18,9 @@
         # need of winsock2.  Remove this when separate compilation is
         # available...
         'winsock2.h',
+        # wincrypt.h defines X509_NAME, include it here
+        # so that openssl/ssl.h can repair this nonsense.
+        'wincrypt.h',
         'openssl/ssl.h',
         'openssl/err.h']
 else:
@@ -88,18 +91,12 @@
     globals()[k] = v
 
 # opaque structures
-SSL_METHOD = rffi.VOIDP
-SSL_CTX = rffi.VOIDP
-SSL = rffi.VOIDP
-BIO = rffi.VOIDP
-X509 = rffi.VOIDP
-X509_NAME = rffi.VOIDP
-
-SSL_CTX_P = rffi.CArrayPtr(SSL_CTX)
-BIO_P = rffi.CArrayPtr(BIO)
-SSL_P = rffi.CArrayPtr(SSL)
-X509_P = rffi.CArrayPtr(X509)
-X509_NAME_P = rffi.CArrayPtr(X509_NAME)
+SSL_METHOD = rffi.COpaquePtr('SSL_METHOD')
+SSL_CTX = rffi.COpaquePtr('SSL_CTX')
+SSL = rffi.COpaquePtr('SSL')
+BIO = rffi.COpaquePtr('BIO')
+X509 = rffi.COpaquePtr('X509')
+X509_NAME = rffi.COpaquePtr('X509_NAME')
 
 HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500f
 
@@ -125,33 +122,33 @@
     ssl_external('RAND_add', [rffi.CCHARP, rffi.INT, rffi.DOUBLE], lltype.Void)
     ssl_external('RAND_status', [], rffi.INT)
     ssl_external('RAND_egd', [rffi.CCHARP], rffi.INT)
-ssl_external('SSL_CTX_new', [rffi.CArrayPtr(SSL_METHOD)], SSL_CTX_P)
-ssl_external('SSLv23_method', [], rffi.CArrayPtr(SSL_METHOD))
-ssl_external('SSL_CTX_use_PrivateKey_file', [SSL_CTX_P, rffi.CCHARP, rffi.INT], rffi.INT)
-ssl_external('SSL_CTX_use_certificate_chain_file', [SSL_CTX_P, rffi.CCHARP], rffi.INT)
-ssl_external('SSL_CTX_ctrl', [SSL_CTX_P, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
-ssl_external('SSL_CTX_set_verify', [SSL_CTX_P, rffi.INT, rffi.VOIDP], lltype.Void)
-ssl_external('SSL_new', [SSL_CTX_P], SSL_P)
-ssl_external('SSL_set_fd', [SSL_P, rffi.INT], rffi.INT)
-ssl_external('BIO_ctrl', [BIO_P, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
-ssl_external('SSL_get_rbio', [SSL_P], BIO_P)
-ssl_external('SSL_get_wbio', [SSL_P], BIO_P)
-ssl_external('SSL_set_connect_state', [SSL_P], lltype.Void)
-ssl_external('SSL_connect', [SSL_P], rffi.INT)
-ssl_external('SSL_get_error', [SSL_P, rffi.INT], rffi.INT)
+ssl_external('SSL_CTX_new', [SSL_METHOD], SSL_CTX)
+ssl_external('SSLv23_method', [], SSL_METHOD)
+ssl_external('SSL_CTX_use_PrivateKey_file', [SSL_CTX, rffi.CCHARP, rffi.INT], rffi.INT)
+ssl_external('SSL_CTX_use_certificate_chain_file', [SSL_CTX, rffi.CCHARP], rffi.INT)
+ssl_external('SSL_CTX_ctrl', [SSL_CTX, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
+ssl_external('SSL_CTX_set_verify', [SSL_CTX, rffi.INT, rffi.VOIDP], lltype.Void)
+ssl_external('SSL_new', [SSL_CTX], SSL)
+ssl_external('SSL_set_fd', [SSL, rffi.INT], rffi.INT)
+ssl_external('BIO_ctrl', [BIO, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
+ssl_external('SSL_get_rbio', [SSL], BIO)
+ssl_external('SSL_get_wbio', [SSL], BIO)
+ssl_external('SSL_set_connect_state', [SSL], lltype.Void)
+ssl_external('SSL_connect', [SSL], rffi.INT)
+ssl_external('SSL_get_error', [SSL, rffi.INT], rffi.INT)
 
 ssl_external('ERR_get_error', [], rffi.INT)
 ssl_external('ERR_error_string', [rffi.ULONG, rffi.CCHARP], rffi.CCHARP)
-ssl_external('SSL_get_peer_certificate', [SSL_P], X509_P)
-ssl_external('X509_get_subject_name', [X509_P], X509_NAME_P)
-ssl_external('X509_get_issuer_name', [X509_P], X509_NAME_P)
-ssl_external('X509_NAME_oneline', [X509_NAME_P, rffi.CCHARP, rffi.INT], rffi.CCHARP)
-ssl_external('X509_free', [X509_P], lltype.Void)
-ssl_external('SSL_free', [SSL_P], lltype.Void)
-ssl_external('SSL_CTX_free', [SSL_CTX_P], lltype.Void)
-ssl_external('SSL_write', [SSL_P, rffi.CCHARP, rffi.INT], rffi.INT)
-ssl_external('SSL_pending', [SSL_P], rffi.INT)
-ssl_external('SSL_read', [SSL_P, rffi.CCHARP, rffi.INT], rffi.INT)
+ssl_external('SSL_get_peer_certificate', [SSL], X509)
+ssl_external('X509_get_subject_name', [X509], X509_NAME)
+ssl_external('X509_get_issuer_name', [X509], X509_NAME)
+ssl_external('X509_NAME_oneline', [X509_NAME, rffi.CCHARP, rffi.INT], rffi.CCHARP)
+ssl_external('X509_free', [X509], lltype.Void)
+ssl_external('SSL_free', [SSL], lltype.Void)
+ssl_external('SSL_CTX_free', [SSL_CTX], lltype.Void)
+ssl_external('SSL_write', [SSL, rffi.CCHARP, rffi.INT], rffi.INT)
+ssl_external('SSL_pending', [SSL], rffi.INT)
+ssl_external('SSL_read', [SSL, rffi.CCHARP, rffi.INT], rffi.INT)
 
 def ssl_error(space, msg):
     w_module = space.getbuiltinmodule('_ssl')
@@ -212,9 +209,9 @@
     def __init__(self, space):
         self.space = space
         self.w_socket = None
-        self.ctx = lltype.nullptr(SSL_CTX_P.TO)
-        self.ssl = lltype.nullptr(SSL_P.TO)
-        self.server_cert = lltype.nullptr(X509_P.TO)
+        self.ctx = lltype.nullptr(SSL_CTX.TO)
+        self.ssl = lltype.nullptr(SSL.TO)
+        self.server_cert = lltype.nullptr(X509.TO)
         self._server = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')
         self._server[0] = '\0'
         self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')

Modified: pypy/branch/fast-forward/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_weakref/interp__weakref.py	Tue Sep 14 16:34:16 2010
@@ -118,7 +118,7 @@
             try:
                 w_self.space.call_function(w_self.w_callable, w_self)
             except OperationError, e:
-                e.write_unraisable(w_self.space, 'function', w_self.w_callable)
+                e.write_unraisable(w_self.space, 'weakref callback ', w_self.w_callable)
 
 
 class W_Weakref(W_WeakrefBase):

Modified: pypy/branch/fast-forward/pypy/module/_winreg/interp_winreg.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_winreg/interp_winreg.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_winreg/interp_winreg.py	Tue Sep 14 16:34:16 2010
@@ -20,16 +20,19 @@
         self.Close(space)
     descr_del.unwrap_spec = ['self', ObjSpace]
 
+    def as_int(self):
+        return rffi.cast(rffi.SIZE_T, self.hkey)
+
     def descr_nonzero(self, space):
-        return space.wrap(self.hkey != 0)
+        return space.wrap(self.as_int() != 0)
     descr_nonzero.unwrap_spec = ['self', ObjSpace]
 
     def descr_repr(self, space):
-        return space.wrap("<PyHKEY:0x%x>" % (self.hkey,))
+        return space.wrap("<PyHKEY:0x%x>" % (self.as_int(),))
     descr_repr.unwrap_spec = ['self', ObjSpace]
 
     def descr_int(self, space):
-        return space.wrap(self.hkey)
+        return space.wrap(self.as_int())
     descr_int.unwrap_spec = ['self', ObjSpace]
 
     def Close(self, space):
@@ -49,12 +52,13 @@
 need the underlying win32 handle to exist beyond the lifetime of the
 handle object.
 On 64 bit windows, the result of this function is a long integer"""
-        hkey = self.hkey
-        self.hkey = 0
-        return space.wrap(hkey)
+        key = self.as_int()
+        self.hkey = rwin32.NULL_HANDLE
+        return space.wrap(key)
     Detach.unwrap_spec = ['self', ObjSpace]
 
-def new_HKEY(space, w_subtype, hkey):
+def new_HKEY(space, w_subtype, key):
+    hkey = rffi.cast(rwinreg.HKEY, key)
     return space.wrap(W_HKEY(hkey))
 descr_HKEY_new = interp2app(new_HKEY,
                             unwrap_spec=[ObjSpace, W_Root, int])
@@ -98,9 +102,9 @@
     elif isinstance(w_hkey, W_HKEY):
         return w_hkey.hkey
     elif space.is_true(space.isinstance(w_hkey, space.w_int)):
-        return space.int_w(w_hkey)
+        return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey))
     elif space.is_true(space.isinstance(w_hkey, space.w_long)):
-        return space.uint_w(w_hkey)
+        return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey))
     else:
         errstring = space.wrap("The object is not a PyHKEY object")
         raise OperationError(space.w_TypeError, errstring)
@@ -631,8 +635,8 @@
                     null_dword, ft)
                 if ret != 0:
                     raiseWindowsError(space, ret, 'RegQueryInfoKey')
-                l = (ft[0].c_dwLowDateTime +
-                     (ft[0].c_dwHighDateTime << 32))
+                l = ((lltype.r_longlong(ft[0].c_dwHighDateTime) << 32) +
+                     lltype.r_longlong(ft[0].c_dwLowDateTime))
                 return space.newtuple([space.wrap(nSubKeys[0]),
                                        space.wrap(nValues[0]),
                                        space.wrap(l)])

Modified: pypy/branch/fast-forward/pypy/module/array/interp_array.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/array/interp_array.py	(original)
+++ pypy/branch/fast-forward/pypy/module/array/interp_array.py	Tue Sep 14 16:34:16 2010
@@ -26,6 +26,11 @@
         raise OperationError(space.w_TypeError, space.wrap(msg))
     typecode = typecode[0]
 
+    if space.is_w(w_cls, space.gettypeobject(W_ArrayBase.typedef)):
+        if len(w_args.keywords_w) > 0:
+            msg = 'array.array() does not take keyword arguments'
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        
     for tc in unroll_typecodes:
         if typecode == tc:
             a = space.allocate_instance(types[tc].w_class, w_cls)
@@ -99,7 +104,6 @@
     def register(typeorder):
         typeorder[W_ArrayBase] = []
 
-
 class TypeCode(object):
     def __init__(self, itemtype, unwrap, canoverflow=False, signed=False):
         self.itemtype = itemtype
@@ -646,12 +650,6 @@
             s = "array('%s', %s)" % (self.typecode, space.str_w(r))
             return space.wrap(s)
 
-    init_signature = Signature(['typecode', 'initializer'])
-    init_defaults = [None, None]
-
-    def init__Array(space, self, args):
-        args.parse_obj(None, 'array', init_signature, init_defaults)
-
     mytype.w_class = W_Array
 
     # Annotator seems to mess up if the names are not unique

Modified: pypy/branch/fast-forward/pypy/module/array/test/test_array.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/array/test/test_array.py	(original)
+++ pypy/branch/fast-forward/pypy/module/array/test/test_array.py	Tue Sep 14 16:34:16 2010
@@ -483,7 +483,6 @@
                 b = self.array(t, v1)
                 c = self.array(t, v2)
 
-                print (a==7)
                 assert (a == 7) is False
                 assert (comparable() == a) is True
                 assert (a == comparable()) is True
@@ -697,7 +696,6 @@
             assert isinstance(self.array(t), self.array)
 
     def test_subclass(self):
-        print type(self.array('b'))
         assert len(self.array('b')) == 0
 
         a = self.array('i')
@@ -708,14 +706,43 @@
 
         class adder(array):
             def __getitem__(self, i):
-                print 25
                 return array.__getitem__(self, i) + 1
 
         a = adder('i', (1, 2, 3))
-        print type(a)
         assert len(a) == 3
         assert a[0] == 2
 
+    def test_subclass_new(self):
+        array = self.array
+        class Image(array):
+            def __new__(cls, width, height, typecode='d'):
+                self = array.__new__(cls, typecode, [0] * (width * height))
+                self.width = width
+                self.height = height
+                return self
+
+            def _index(self, (x,y)):
+                x = min(max(x, 0), self.width-1)
+                y = min(max(y, 0), self.height-1)
+                return y * self.width + x
+
+            def __getitem__(self, i):
+                return array.__getitem__(self, self._index(i))
+            
+            def __setitem__(self, i, val):
+                return array.__setitem__(self, self._index(i), val)
+
+        img = Image(5, 10, 'B')
+        for y in range(10):
+            for x in range(5):
+                img[x, y] = x * y
+        for y in range(10):
+            for x in range(5):
+                assert img[x, y] == x * y
+
+        assert img[3, 25] == 3 * 9
+
+                
     def test_override_from(self):
         class mya(self.array):
             def fromlist(self, lst):

Modified: pypy/branch/fast-forward/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/interp_jit.py	Tue Sep 14 16:34:16 2010
@@ -36,11 +36,13 @@
     bytecode.jit_cells[next_instr] = newcell
 
 def confirm_enter_jit(next_instr, bytecode, frame, ec):
-    return (not (bytecode.co_flags & CO_GENERATOR) and
-            frame.w_f_trace is None and
+    return (frame.w_f_trace is None and
             ec.profilefunc is None and
             ec.w_tracefunc is None)
 
+def can_never_inline(next_instr, bytecode):
+    return (bytecode.co_flags & CO_GENERATOR) != 0
+
 
 class PyPyJitDriver(JitDriver):
     reds = ['frame', 'ec']
@@ -58,7 +60,8 @@
 pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location,
                               get_jitcell_at = get_jitcell_at,
                               set_jitcell_at = set_jitcell_at,
-                              confirm_enter_jit = confirm_enter_jit)
+                              confirm_enter_jit = confirm_enter_jit,
+                              can_never_inline = can_never_inline)
 
 class __extend__(PyFrame):
 

Modified: pypy/branch/fast-forward/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/policy.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/policy.py	Tue Sep 14 16:34:16 2010
@@ -32,8 +32,6 @@
             return False
         if mod.startswith('pypy.interpreter.pyparser.'):
             return False
-        if mod == 'pypy.interpreter.generator':
-            return False
         if mod.startswith('pypy.module.'):
             modname = mod[len('pypy.module.'):]
             if not self.look_inside_pypy_module(modname):

Modified: pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	Tue Sep 14 16:34:16 2010
@@ -110,6 +110,7 @@
 
         if sys.platform.startswith('win'):
             py.test.skip("XXX this is not Windows-friendly")
+        print logfilepath
         child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
             logfilepath, self.pypy_c, filepath), 'r')
         result = child_stdout.read()
@@ -118,6 +119,7 @@
         assert result.splitlines()[-1].strip() == 'OK :-)'
         self.parse_loops(logfilepath)
         self.print_loops()
+        print logfilepath
         if self.total_ops > expected_max_ops:
             assert 0, "too many operations: got %d, expected maximum %d" % (
                 self.total_ops, expected_max_ops)
@@ -846,6 +848,221 @@
                 return intimg[i - 1]
             ''', maxops, ([tc], res))
 
+    def test_intbound_simple(self):
+        ops = ('<', '>', '<=', '>=', '==', '!=')
+        nbr = (3, 7)
+        for o1 in ops:
+            for o2 in ops:
+                for n1 in nbr:
+                    for n2 in nbr:
+                        src = '''
+                        def f(i):
+                            a, b = 3, 3
+                            if i %s %d:
+                                a = 0
+                            else:
+                                a = 1
+                            if i %s %d:
+                                b = 0
+                            else:
+                                b = 1
+                            return a + b * 2
+
+                        def main():
+                            res = [0] * 4
+                            idx = []
+                            for i in range(15):
+                                idx.extend([i] * 1500)
+                            for i in idx:
+                                res[f(i)] += 1
+                            return res
+
+                        ''' % (o1, n1, o2, n2)
+
+                        exec(str(py.code.Source(src)))
+                        res = [0] * 4
+                        for i in range(15):
+                            res[f(i)] += 1500
+                        self.run_source(src, 268, ([], res))
+
+    def test_intbound_addsub_mix(self):
+        tests = ('i > 4', 'i > 2', 'i + 1 > 2', '1 + i > 4',
+                 'i - 1 > 1', '1 - i > 1', '1 - i < -3',
+                 'i == 1', 'i == 5', 'i != 1', '-2 * i < -4')
+        for t1 in tests:
+            for t2 in tests:
+                print t1, t2
+                src = '''
+                def f(i):
+                    a, b = 3, 3
+                    if %s:
+                        a = 0
+                    else:
+                        a = 1
+                    if %s:
+                        b = 0
+                    else:
+                        b = 1
+                    return a + b * 2
+
+                def main():
+                    res = [0] * 4
+                    idx = []
+                    for i in range(15):
+                        idx.extend([i] * 1500)
+                    for i in idx:
+                        res[f(i)] += 1
+                    return res
+
+                ''' % (t1, t2)
+
+                exec(str(py.code.Source(src)))
+                res = [0] * 4
+                for i in range(15):
+                    res[f(i)] += 1500
+                self.run_source(src, 280, ([], res))
+
+    def test_intbound_gt(self):
+        self.run_source('''
+        def main():
+            i, a, b = 0, 0, 0
+            while i < 2000:
+                if i > -1:
+                    a += 1
+                if i > -2:
+                    b += 1
+                i += 1
+            return (a, b)
+        ''', 48, ([], (2000, 2000)))
+
+    def test_intbound_sub_lt(self):
+        self.run_source('''
+        def main():
+            i, a, b = 0, 0, 0
+            while i < 2000:
+                if i - 10 < 1995:
+                    a += 1
+                i += 1
+            return (a, b)
+        ''', 38, ([], (2000, 0)))
+
+    def test_intbound_addsub_ge(self):
+        self.run_source('''
+        def main():
+            i, a, b = 0, 0, 0
+            while i < 2000:
+                if i + 5 >= 5:
+                    a += 1
+                if i - 1 >= -1:
+                    b += 1
+                i += 1
+            return (a, b)
+        ''', 56, ([], (2000, 2000)))
+
+    def test_intbound_addmul_ge(self):
+        self.run_source('''
+        def main():
+            i, a, b = 0, 0, 0
+            while i < 2000:
+                if i + 5 >= 5:
+                    a += 1
+                if 2 * i >= 0:
+                    b += 1
+                i += 1
+            return (a, b)
+        ''', 53, ([], (2000, 2000)))
+
+    def test_intbound_eq(self):
+        self.run_source('''
+        def main(a):
+            i, s = 0, 0
+            while i < 1500:
+                if a == 7:
+                    s += a + 1
+                elif i == 10:
+                    s += i
+                else:
+                    s += 1
+                i += 1
+            return s
+        ''', 69, ([7], 12000), ([42], 1509), ([10], 1509))
+        
+    def test_intbound_mul(self):
+        self.run_source('''
+        def main(a):
+            i, s = 0, 0
+            while i < 1500:
+                assert i >= 0
+                if 2 * i < 30000:
+                    s += 1
+                else:
+                    s += a
+                i += 1
+            return s
+        ''', 43, ([7], 1500))
+        
+    def test_assert(self):
+        self.run_source('''
+        def main(a):
+            i, s = 0, 0
+            while i < 1500:
+                assert a == 7
+                s += a + 1
+                i += 1
+            return s
+        ''', 38, ([7], 8*1500))
+        
+    def test_zeropadded(self):
+        self.run_source('''
+        from array import array
+        class ZeroPadded(array):
+            def __new__(cls, l):
+                self = array.__new__(cls, 'd', range(l))
+                return self
+
+            def __getitem__(self, i):
+                if i < 0 or i >= self.__len__():
+                    return 0
+                return array.__getitem__(self, i)
+
+
+        def main():
+            buf = ZeroPadded(2000)
+            i = 10
+            sa = 0
+            while i < 2000 - 10:
+                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
+                i += 1
+            return sa
+
+        ''', 232, ([], 9895050.0))
+
+    def test_circular(self):
+        self.run_source('''
+        from array import array
+        class Circular(array):
+            def __new__(cls):
+                self = array.__new__(cls, 'd', range(256))
+                return self
+            def __getitem__(self, i):
+                # assert self.__len__() == 256 (FIXME: does not improve)
+                return array.__getitem__(self, i & 255)
+
+        def main():
+            buf = Circular()
+            i = 10
+            sa = 0
+            while i < 2000 - 10:
+                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
+                i += 1
+            return sa
+
+        ''', 170, ([], 1239690.0))
+
+        
+
+    # test_circular
+
 class AppTestJIT(PyPyCJITTests):
     def setup_class(cls):
         if not option.runappdirect:

Modified: pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py	Tue Sep 14 16:34:16 2010
@@ -32,6 +32,9 @@
                 'arpa/inet.h',
                 'stdint.h', 
                 'errno.h',
+                'netpacket/packet.h',
+                'sys/ioctl.h',
+                'net/if.h',
                 )
     cond_includes = [('AF_NETLINK', 'linux/netlink.h')]
     libraries = ()
@@ -190,6 +193,8 @@
 FD_CONNECT_BIT FD_CLOSE_BIT
 WSA_IO_PENDING WSA_IO_INCOMPLETE WSA_INVALID_HANDLE
 WSA_INVALID_PARAMETER WSA_NOT_ENOUGH_MEMORY WSA_OPERATION_ABORTED
+
+SIOCGIFNAME
 '''.split()
 
 for name in constant_names:
@@ -309,6 +314,19 @@
                                             [('fd', socketfd_type),
                                              ('events', rffi.SHORT),
                                              ('revents', rffi.SHORT)])
+
+    CConfig.sockaddr_ll = platform.Struct('struct sockaddr_ll',
+                              [('sll_ifindex', rffi.INT),
+                               ('sll_protocol', rffi.INT),
+                               ('sll_pkttype', rffi.INT),
+                               ('sll_hatype', rffi.INT),
+                               ('sll_addr', rffi.CFixedArray(rffi.CHAR, 8)),
+                               ('sll_halen', rffi.INT)],
+                              )
+
+    CConfig.ifreq = platform.Struct('struct ifreq', [('ifr_ifindex', rffi.INT),
+                                 ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))])
+
 if _WIN32:
     CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP)
     CConfig.WSANETWORKEVENTS = platform.Struct(
@@ -408,6 +426,8 @@
 if _POSIX:
     nfds_t = cConfig.nfds_t
     pollfd = cConfig.pollfd
+    sockaddr_ll = cConfig.sockaddr_ll
+    ifreq = cConfig.ifreq
 if WIN32:
     WSAEVENT = cConfig.WSAEVENT
     WSANETWORKEVENTS = cConfig.WSANETWORKEVENTS
@@ -510,6 +530,8 @@
     socketpair_t = rffi.CArray(socketfd_type)
     socketpair = external('socketpair', [rffi.INT, rffi.INT, rffi.INT,
                           lltype.Ptr(socketpair_t)], rffi.INT)
+    ioctl = external('ioctl', [socketfd_type, rffi.INT, lltype.Ptr(ifreq)],
+                     rffi.INT)
 
 if _WIN32:
     ioctlsocket = external('ioctlsocket',

Modified: pypy/branch/fast-forward/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/jit.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/jit.py	Tue Sep 14 16:34:16 2010
@@ -253,7 +253,8 @@
     
     def __init__(self, greens=None, reds=None, virtualizables=None,
                  get_jitcell_at=None, set_jitcell_at=None,
-                 get_printable_location=None, confirm_enter_jit=None):
+                 get_printable_location=None, confirm_enter_jit=None,
+                 can_never_inline=None):
         if greens is not None:
             self.greens = greens
         if reds is not None:
@@ -270,6 +271,7 @@
         self.set_jitcell_at = set_jitcell_at
         self.get_printable_location = get_printable_location
         self.confirm_enter_jit = confirm_enter_jit
+        self.can_never_inline = can_never_inline
 
     def _freeze_(self):
         return True

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	Tue Sep 14 16:34:16 2010
@@ -72,6 +72,7 @@
         setattr(CConfig, name, rffi_platform.ConstantInteger(name))
 
     from pypy.rlib.rwin32 import HANDLE, LPHANDLE
+    from pypy.rlib.rwin32 import NULL_HANDLE, INVALID_HANDLE_VALUE
     from pypy.rlib.rwin32 import DWORD, WORD, DWORD_PTR, LPDWORD
     from pypy.rlib.rwin32 import BOOL, LPVOID, LPCVOID, LPCSTR, SIZE_T
     from pypy.rlib.rwin32 import INT, LONG, PLONG
@@ -183,7 +184,7 @@
     ##_get_osfhandle = winexternal('_get_osfhandle', [INT], LONG)
     # casting from int to handle did not work, so I changed this
     # but it should not be so!
-    _get_osfhandle = winexternal('_get_osfhandle', [INT], HANDLE)
+    _get_osfhandle = winexternal('_get_osfhandle', [INT], rffi.INTPTR_T)
     GetLastError = winexternal('GetLastError', [], DWORD)
     VirtualAlloc = winexternal('VirtualAlloc',
                                [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD],
@@ -228,8 +229,7 @@
     def _get_error_no():
         return rffi.cast(lltype.Signed, GetLastError())
 
-    NULL_HANDLE = rffi.cast(HANDLE, 0)
-    INVALID_HANDLE = rffi.cast(HANDLE, -1)
+    INVALID_HANDLE = INVALID_HANDLE_VALUE
 
 PAGESIZE = _get_page_size()
 NULL = lltype.nullptr(PTR.TO)
@@ -684,12 +684,11 @@
         # assume -1 and 0 both mean invalid file descriptor
         # to 'anonymously' map memory.
         if fileno != -1 and fileno != 0:
-            fh = _get_osfhandle(fileno)
-            # parts of the C library use HANDLE, others just ints
-            # XXX hack - made _get_osfhandle compatible
-            if fh == INVALID_HANDLE:
+            res = _get_osfhandle(fileno)
+            if res == rffi.cast(rffi.SSIZE_T, INVALID_HANDLE):
                 errno = _get_error_no()
                 raise OSError(errno, os.strerror(errno))
+            fh = rffi.cast(HANDLE, res)
             # Win9x appears to need us seeked to zero
             # SEEK_SET = 0
             # libc._lseek(fileno, 0, SEEK_SET)

Modified: pypy/branch/fast-forward/pypy/rlib/rsocket.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rsocket.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rsocket.py	Tue Sep 14 16:34:16 2010
@@ -6,8 +6,7 @@
 
 # Known missing features:
 #
-#   - support for non-Linux platforms
-#   - address families other than AF_INET, AF_INET6, AF_UNIX
+#   - address families other than AF_INET, AF_INET6, AF_UNIX, AF_PACKET
 #   - methods makefile(),
 #   - SSL
 #
@@ -109,7 +108,7 @@
         """
         keepalive_until_here(self)
 
-    def as_object(self, space):
+    def as_object(self, fd, space):
         """Convert the address to an app-level object."""
         # If we don't know the address family, don't raise an
         # exception -- return it as a tuple.
@@ -200,6 +199,66 @@
 
 # ____________________________________________________________
 
+if 'AF_PACKET' in constants:
+    class PacketAddress(Address):
+        family = AF_PACKET
+        struct = _c.sockaddr_ll
+        maxlen = minlen = sizeof(struct)
+
+        def get_ifname(self, fd):
+            a = self.lock(_c.sockaddr_ll)
+            p = lltype.malloc(_c.ifreq, flavor='raw')
+            rffi.setintfield(p, 'c_ifr_ifindex',
+                             rffi.getintfield(a, 'c_sll_ifindex'))
+            if (_c.ioctl(fd, _c.SIOCGIFNAME, p) == 0):
+                # eh, the iface name is a constant length array
+                i = 0
+                d = []
+                while p.c_ifr_name[i] != '\x00' and i < len(p.c_ifr_name):
+                    d.append(p.c_ifr_name[i])
+                    i += 1
+                ifname = ''.join(d)
+            else:
+                ifname = ""
+            lltype.free(p, flavor='raw')
+            self.unlock()
+            return ifname
+
+        def get_protocol(self):
+            a = self.lock(_c.sockaddr_ll)
+            res = ntohs(rffi.getintfield(a, 'c_sll_protocol'))
+            self.unlock()
+            return res
+
+        def get_pkttype(self):
+            a = self.lock(_c.sockaddr_ll)
+            res = rffi.getintfield(a, 'c_sll_pkttype')
+            self.unlock()
+            return res
+
+        def get_hatype(self):
+            a = self.lock(_c.sockaddr_ll)
+            res = bool(rffi.getintfield(a, 'c_sll_hatype'))
+            self.unlock()
+            return res
+
+        def get_addr(self):
+            a = self.lock(_c.sockaddr_ll)
+            lgt = rffi.getintfield(a, 'c_sll_halen')
+            d = []
+            for i in range(lgt):
+                d.append(a.c_sll_addr[i])
+            res = "".join(d)
+            self.unlock()
+            return res
+
+        def as_object(self, fd, space):
+            return space.newtuple([space.wrap(self.get_ifname(fd)),
+                                   space.wrap(self.get_protocol()),
+                                   space.wrap(self.get_pkttype()),
+                                   space.wrap(self.get_hatype()),
+                                   space.wrap(self.get_addr())])
+
 class INETAddress(IPAddress):
     family = AF_INET
     struct = _c.sockaddr_in
@@ -228,7 +287,7 @@
                 self.get_host() == other.get_host() and
                 self.get_port() == other.get_port())
 
-    def as_object(self, space):
+    def as_object(self, fd, space):
         return space.newtuple([space.wrap(self.get_host()),
                                space.wrap(self.get_port())])
 
@@ -317,7 +376,7 @@
                 self.get_flowinfo() == other.get_flowinfo() and
                 self.get_scope_id() == other.get_scope_id())
 
-    def as_object(self, space):
+    def as_object(self, fd, space):
         return space.newtuple([space.wrap(self.get_host()),
                                space.wrap(self.get_port()),
                                space.wrap(self.get_flowinfo()),
@@ -421,7 +480,7 @@
             return (isinstance(other, UNIXAddress) and
                     self.get_path() == other.get_path())
 
-        def as_object(self, space):
+        def as_object(self, fd, space):
             return space.wrap(self.get_path())
 
         def from_object(space, w_address):
@@ -456,7 +515,7 @@
         def __repr__(self):
             return '<NETLINKAddress %r>' % (self.get_pid(), self.get_groups())
         
-        def as_object(self, space):
+        def as_object(self, fd, space):
             return space.newtuple([space.wrap(self.get_pid()),
                                    space.wrap(self.get_groups())])
 
@@ -613,7 +672,7 @@
 
     # convert an Address into an app-level object
     def addr_as_object(self, space, address):
-        return address.as_object(space)
+        return address.as_object(self.fd, space)
 
     # convert an app-level object into an Address
     # based on the current socket's family

Modified: pypy/branch/fast-forward/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rwin32.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rwin32.py	Tue Sep 14 16:34:16 2010
@@ -81,9 +81,10 @@
     return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win')
 
 if WIN32:
-    HANDLE = rffi.ULONG
+    HANDLE = rffi.COpaquePtr(typedef='HANDLE')
     LPHANDLE = rffi.CArrayPtr(HANDLE)
     HMODULE = HANDLE
+    NULL_HANDLE = rffi.cast(HANDLE, 0)
     INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1)
     PFILETIME = rffi.CArrayPtr(FILETIME)
 

Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py	Tue Sep 14 16:34:16 2010
@@ -358,9 +358,11 @@
 if os.name != 'nt':
     TYPES.append('mode_t')
     TYPES.append('pid_t')
+    TYPES.append('ssize_t')
 else:
     MODE_T = lltype.Signed
     PID_T = lltype.Signed
+    SSIZE_T = lltype.Signed
 
 def populate_inttypes():
     names = []
@@ -415,6 +417,7 @@
 #        ULONGLONG      r_ulonglong
 #        WCHAR_T        r_wchar_t
 #        SIZE_T         r_size_t
+#        SSIZE_T        r_ssize_t
 #        TIME_T         r_time_t
 # --------------------------------------------------------------------
 # Note that rffi.r_int is not necessarily the same as
@@ -535,6 +538,8 @@
 # (use SIGNEDCHAR or UCHAR for the small integer types)
 CHAR = lltype.Char
 
+INTPTR_T = SSIZE_T
+
 # double
 DOUBLE = lltype.Float
 

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	Tue Sep 14 16:34:16 2010
@@ -1046,7 +1046,7 @@
                                                         rffi.VOIDP,
                                                         rwin32.DWORD],
                                          rwin32.BOOL)
-            _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.ULONG,
+            _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.INTPTR_T,
                                                                   rffi.INT],
                                               rffi.INT)
             null = lltype.nullptr(rffi.VOIDP.TO)
@@ -1059,8 +1059,8 @@
                     error = 0
                 else:
                     error = rwin32.GetLastError()
-                hread = pread[0]
-                hwrite = pwrite[0]
+                hread = rffi.cast(rffi.INTPTR_T, pread[0])
+                hwrite = rffi.cast(rffi.INTPTR_T, pwrite[0])
                 lltype.free(pwrite, flavor='raw')
                 lltype.free(pread, flavor='raw')
                 if error:

Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_os_stat.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_os_stat.py	Tue Sep 14 16:34:16 2010
@@ -437,5 +437,5 @@
 def time_t_to_FILE_TIME(time, filetime):
     ft = lltype.r_longlong((time + secs_between_epochs) * 10000000)
     filetime.c_dwHighDateTime = lltype.r_uint(ft >> 32)
-    filetime.c_dwLowDateTime = lltype.r_uint(ft & ((1 << 32) - 1))
+    filetime.c_dwLowDateTime = lltype.r_uint(ft & lltype.r_uint(-1))
 

Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_win32file.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_win32file.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_win32file.py	Tue Sep 14 16:34:16 2010
@@ -265,7 +265,8 @@
         hFile = CreateFile(path,
                            FILE_WRITE_ATTRIBUTES, 0,
                            None, OPEN_EXISTING,
-                           FILE_FLAG_BACKUP_SEMANTICS, 0)
+                           FILE_FLAG_BACKUP_SEMANTICS,
+                           rwin32.NULL_HANDLE)
         if hFile == rwin32.INVALID_HANDLE_VALUE:
             raise rwin32.lastWindowsError()
         ctime = lltype.nullptr(rwin32.FILETIME)

Modified: pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py	Tue Sep 14 16:34:16 2010
@@ -11,6 +11,7 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import CompilationError
 from pypy.tool.udir import udir
+from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, intmask
 
 # ____________________________________________________________
 #
@@ -380,7 +381,7 @@
         yield '}'
 
     def build_result(self, info, config_result):
-        return info['value']
+        return expose_value_as_rpython(info['value'])
 
 class DefinedConstantInteger(CConfigEntry):
     """An entry in a CConfig class that stands for an externally
@@ -406,7 +407,7 @@
 
     def build_result(self, info, config_result):
         if info["defined"]:
-            return info['value']
+            return expose_value_as_rpython(info['value'])
         return None
 
 class DefinedConstantDouble(CConfigEntry):
@@ -654,6 +655,20 @@
     raise TypeError("conflicting field type %r for %r" % (fieldtype,
                                                           fieldname))
 
+def expose_value_as_rpython(value):
+    if intmask(value) == value:
+        return value
+    if r_uint(value) == value:
+        return r_uint(value)
+    try:
+        if r_longlong(value) == value:
+            return r_longlong(value)
+    except OverflowError:
+        pass
+    if r_ulonglong(value) == value:
+        return r_ulonglong(value)
+    raise OverflowError("value %d does not fit into any RPython integer type"
+                        % (value,))
 
 C_HEADER = """
 #include <stdio.h>

Modified: pypy/branch/fast-forward/pypy/rpython/tool/test/test_rffi_platform.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/tool/test/test_rffi_platform.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/tool/test/test_rffi_platform.py	Tue Sep 14 16:34:16 2010
@@ -5,7 +5,7 @@
 from pypy.tool.udir import udir
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform
-from pypy.rlib import rarithmetic
+from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, isnan
 
 def import_ctypes():
     try:
@@ -117,7 +117,7 @@
     value = rffi_platform.getdefineddouble('BLAH', '#define BLAH 1.0e50000')
     assert value == float("inf")
     value = rffi_platform.getdefineddouble('BLAH', '#define BLAH (double)0/0')
-    assert rarithmetic.isnan(value)
+    assert isnan(value)
 
 def test_configure():
     test_h = udir.join('test_ctypes_platform.h')
@@ -370,3 +370,19 @@
     padding = list(S._hints['padding'])
     d = {'c_c1': 'char'}
     assert S._hints['get_padding_drop'](d) == padding
+
+def test_expose_value_as_rpython():
+    def get(x):
+        x = rffi_platform.expose_value_as_rpython(x)
+        return (x, type(x))
+    assert get(5) == (5, int)
+    assert get(-82) == (-82, int)
+    assert get(sys.maxint) == (sys.maxint, int)
+    assert get(sys.maxint+1) == (sys.maxint+1, r_uint)
+    if sys.maxint == 2147483647:
+        assert get(9999999999) == (9999999999, r_longlong)
+        assert get(-9999999999) == (-9999999999, r_longlong)
+        assert get(2**63) == (2**63, r_ulonglong)
+        assert get(-2**63) == (-2**63, r_longlong)
+    py.test.raises(OverflowError, get, -2**63-1)
+    py.test.raises(OverflowError, get, 2**64)

Modified: pypy/branch/fast-forward/pypy/tool/release/force-builds.py
==============================================================================
--- pypy/branch/fast-forward/pypy/tool/release/force-builds.py	(original)
+++ pypy/branch/fast-forward/pypy/tool/release/force-builds.py	Tue Sep 14 16:34:16 2010
@@ -21,9 +21,9 @@
     'own-linux-x86-64',
 #    'own-macosx-x86-32',
     'pypy-c-app-level-linux-x86-32',
-    'pypy-c-app-level-linux-64',
+    'pypy-c-app-level-linux-x86-64',
     'pypy-c-stackless-app-level-linux-x86-32',
-    'pypy-c-app-level-win-32',
+    'pypy-c-app-level-win-x86-32',
     'pypy-c-jit-linux-x86-32',
 #    'pypy-c-jit-macosx-x86-32',
     'pypy-c-jit-win-x86-32',

Modified: pypy/branch/fast-forward/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/database.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/database.py	Tue Sep 14 16:34:16 2010
@@ -2,7 +2,7 @@
      Primitive, Ptr, typeOf, RuntimeTypeInfo, \
      Struct, Array, FuncType, PyObject, Void, \
      ContainerType, OpaqueType, FixedSizeArray, _uninitialized
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType, GCREF
 from pypy.rpython.lltypesystem.rffi import CConstant
 from pypy.rpython.lltypesystem import llgroup
@@ -183,6 +183,12 @@
         if isinstance(T, Primitive) or T == GCREF:
             return PrimitiveName[T](obj, self)
         elif isinstance(T, Ptr):
+            if (isinstance(T.TO, OpaqueType) and
+                T.TO.hints.get('c_pointer_typedef') is not None):
+                if obj._obj is not None:
+                    value = rffi.cast(rffi.SSIZE_T, obj)
+                    return '((%s) %s)' % (cdecl(self.gettype(T), ''),
+                                          self.get(value))
             if obj:   # test if the ptr is non-NULL
                 try:
                     container = obj._obj



More information about the Pypy-commit mailing list