[pypy-svn] r67624 - in pypy/branch/spine-of-frames/pypy: annotation annotation/test config doc/config interpreter interpreter/astcompiler/tools interpreter/test jit/backend jit/backend/llgraph jit/backend/llsupport jit/backend/llsupport/test jit/backend/test jit/backend/x86 jit/backend/x86/test jit/metainterp jit/metainterp/test jit/tl module/__builtin__ module/_ast module/_ast/test module/_pickle_support module/_testing module/parser module/parser/test module/posix module/posix/test module/pypyjit module/pypyjit/test/loops module/token module/token/test objspace/std objspace/std/test rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gc rpython/memory/gctransform rpython/module rpython/ootypesystem rpython/ootypesystem/test rpython/test translator translator/c translator/c/gcc translator/c/gcc/test translator/c/src translator/c/test translator/cli translator/jvm translator/platform translator/tool

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Sep 10 16:45:17 CEST 2009


Author: cfbolz
Date: Thu Sep 10 16:45:13 2009
New Revision: 67624

Added:
   pypy/branch/spine-of-frames/pypy/doc/config/objspace.std.newshortcut.txt
      - copied unchanged from r67623, pypy/trunk/pypy/doc/config/objspace.std.newshortcut.txt
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_gc_integration.py
      - copied unchanged from r67623, pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_recompilation.py
      - copied unchanged from r67623, pypy/trunk/pypy/jit/backend/x86/test/test_recompilation.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_executor.py
      - copied unchanged from r67623, pypy/trunk/pypy/jit/metainterp/test/test_executor.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_float.py
      - copied unchanged from r67623, pypy/trunk/pypy/jit/metainterp/test/test_float.py
   pypy/branch/spine-of-frames/pypy/rlib/rweakref.py
      - copied unchanged from r67623, pypy/trunk/pypy/rlib/rweakref.py
   pypy/branch/spine-of-frames/pypy/rlib/rweakrefimpl.py
      - copied unchanged from r67623, pypy/trunk/pypy/rlib/rweakrefimpl.py
   pypy/branch/spine-of-frames/pypy/rlib/test/test_rweakref.py
      - copied unchanged from r67623, pypy/trunk/pypy/rlib/test/test_rweakref.py
Modified:
   pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py
   pypy/branch/spine-of-frames/pypy/annotation/builtin.py
   pypy/branch/spine-of-frames/pypy/annotation/classdef.py
   pypy/branch/spine-of-frames/pypy/annotation/model.py
   pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py
   pypy/branch/spine-of-frames/pypy/annotation/unaryop.py
   pypy/branch/spine-of-frames/pypy/config/pypyoption.py
   pypy/branch/spine-of-frames/pypy/interpreter/astcompiler/tools/   (props changed)
   pypy/branch/spine-of-frames/pypy/interpreter/error.py
   pypy/branch/spine-of-frames/pypy/interpreter/function.py
   pypy/branch/spine-of-frames/pypy/interpreter/pycode.py
   pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py
   pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py
   pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py
   pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py
   pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py
   pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py
   pypy/branch/spine-of-frames/pypy/jit/backend/model.py
   pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py
   pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py
   pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py
   pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py
   pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py
   pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py
   pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py
   pypy/branch/spine-of-frames/pypy/module/_ast/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/_ast/__init__.py   (props changed)
   pypy/branch/spine-of-frames/pypy/module/_ast/test/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/_ast/test/__init__.py   (props changed)
   pypy/branch/spine-of-frames/pypy/module/_ast/test/test_ast.py   (props changed)
   pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py
   pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py
   pypy/branch/spine-of-frames/pypy/module/_testing/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/parser/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/parser/test/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py
   pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py
   pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py
   pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/dict_lookup.py   (props changed)
   pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/simple_add.py   (props changed)
   pypy/branch/spine-of-frames/pypy/module/token/   (props changed)
   pypy/branch/spine-of-frames/pypy/module/token/test/   (props changed)
   pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py
   pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py
   pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py
   pypy/branch/spine-of-frames/pypy/rlib/jit.py
   pypy/branch/spine-of-frames/pypy/rlib/libffi.py
   pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py
   pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py
   pypy/branch/spine-of-frames/pypy/rlib/rwin32.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py
   pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py
   pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py
   pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py
   pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py
   pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py
   pypy/branch/spine-of-frames/pypy/rpython/rint.py
   pypy/branch/spine-of-frames/pypy/rpython/rpbc.py
   pypy/branch/spine-of-frames/pypy/rpython/rtyper.py
   pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py
   pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py
   pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py
   pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py
   pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/spine-of-frames/pypy/translator/c/genc.py
   pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h
   pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py
   pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py
   pypy/branch/spine-of-frames/pypy/translator/driver.py
   pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py
   pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py
   pypy/branch/spine-of-frames/pypy/translator/platform/posix.py
   pypy/branch/spine-of-frames/pypy/translator/platform/windows.py
   pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py
Log:
merge in changes from revisions r67429 through r67623 of trunk.


Modified: pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py	Thu Sep 10 16:45:13 2009
@@ -11,8 +11,8 @@
      SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
      SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \
      SomeWeakRef, lltype_to_annotation
-from pypy.annotation.classdef import InstanceSource
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.classdef import InstanceSource, ClassDef
+from pypy.annotation.listdef import ListDef, ListItem
 from pypy.annotation.dictdef import DictDef
 from pypy.annotation import description
 from pypy.annotation.signature import annotationoftype
@@ -228,6 +228,38 @@
         finally:
             self.leave()
 
+        # sanity check: no flags attached to heap stored instances
+
+        seen = set()
+
+        def check_no_flags(s_value_or_def):
+            if isinstance(s_value_or_def, SomeInstance):
+                assert not s_value_or_def.flags, "instance annotation with flags escaped to the heap"
+                check_no_flags(s_value_or_def.classdef)
+            elif isinstance(s_value_or_def, SomeList):
+                check_no_flags(s_value_or_def.listdef.listitem)
+            elif isinstance(s_value_or_def, SomeDict):
+                check_no_flags(s_value_or_def.dictdef.dictkey)
+                check_no_flags(s_value_or_def.dictdef.dictvalue)                
+            elif isinstance(s_value_or_def, SomeTuple):
+                for s_item in s_value_or_def.items:
+                    check_no_flags(s_item)
+            elif isinstance(s_value_or_def, ClassDef):
+                if s_value_or_def in seen:
+                    return
+                seen.add(s_value_or_def)
+                for attr in s_value_or_def.attrs.values():
+                    s_attr = attr.s_value
+                    check_no_flags(s_attr)
+            elif isinstance(s_value_or_def, ListItem):
+                if s_value_or_def in seen:
+                    return
+                seen.add(s_value_or_def)                
+                check_no_flags(s_value_or_def.s_value)
+            
+        for clsdef in self.classdefs:
+            check_no_flags(clsdef)
+
     def consider_call_site(self, call_op):
         binding = self.annotator.binding
         s_callable = binding(call_op.args[0])

Modified: pypy/branch/spine-of-frames/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/builtin.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/builtin.py	Thu Sep 10 16:45:13 2009
@@ -270,6 +270,9 @@
 def OSError_init(s_self, *args):
     pass
 
+def WindowsError_init(s_self, *args):
+    pass
+
 def termios_error_init(s_self, *args):
     pass
 
@@ -386,6 +389,15 @@
 BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = (
     OSError_init)
 
+try:
+    WindowsError
+except NameError:
+    pass
+else:
+    BUILTIN_ANALYZERS[getattr(WindowsError.__init__, 'im_func',
+                              WindowsError.__init__)] = (
+        WindowsError_init)
+
 BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf
 try:
     import unicodedata

Modified: pypy/branch/spine-of-frames/pypy/annotation/classdef.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/classdef.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/classdef.py	Thu Sep 10 16:45:13 2009
@@ -442,6 +442,13 @@
     }
 
 try:
+    WindowsError
+except NameError:
+    pass
+else:
+    FORCE_ATTRIBUTES_INTO_CLASSES[WindowsError] = {'winerror': SomeInteger()}
+
+try:
     import termios
 except ImportError:
     pass

Modified: pypy/branch/spine-of-frames/pypy/annotation/model.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/model.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/model.py	Thu Sep 10 16:45:13 2009
@@ -632,15 +632,6 @@
         # i think we can only get here in the case of void-returning
         # functions
         return s_None
-    if isinstance(v, MethodType):
-        ll_ptrtype = lltype.typeOf(v.im_self)
-        assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
-        return SomeLLADTMeth(ll_ptrtype, v.im_func)
-    if isinstance(v, FunctionType):
-        # this case should only be for staticmethod instances used in
-        # adtmeths: the getattr() result is then a plain FunctionType object.
-        from pypy.annotation.bookkeeper import getbookkeeper
-        return getbookkeeper().immutablevalue(v)
     if isinstance(v, lltype._interior_ptr):
         ob = v._parent
         if ob is None:

Modified: pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py	Thu Sep 10 16:45:13 2009
@@ -2785,6 +2785,64 @@
         assert isinstance(s.items[2], annmodel.SomeInstance)
         assert s.items[2].flags == {}
 
+    def test_no_access_directly_on_heap(self):
+        from pypy.rlib.jit import hint
+
+        class A:
+            _virtualizable2_ = []
+
+        class I:
+            pass
+
+        def f():
+            x = A()
+            x = hint(x, access_directly=True)
+            i = I()
+            i.x = x
+
+        a = self.RPythonAnnotator()
+        py.test.raises(Exception, a.build_types, f, [])        
+
+
+        class M:
+            def __init__(self):
+                self.l = []
+                self.d = {}
+
+        class C:
+            def _freeze_(self):
+                return True
+
+            def __init__(self):
+                self.m = M()
+                self.l2 = []
+
+        c = C()
+         
+        def f():
+            x = A()
+            x = hint(x, access_directly=True)
+            c.m.l.append(x)
+
+        a = self.RPythonAnnotator()
+        py.test.raises(AssertionError, a.build_types, f, [])        
+
+        def f():
+            x = A()
+            x = hint(x, access_directly=True)
+            c.m.d[None] = x
+            
+        a = self.RPythonAnnotator()
+        py.test.raises(AssertionError, a.build_types, f, [])        
+
+        def f():
+            x = A()
+            x = hint(x, access_directly=True)
+            c.m.d[x] = None
+            
+        a = self.RPythonAnnotator()
+        py.test.raises(AssertionError, a.build_types, f, [])        
+
     def test_ctr_location(self):
         from pypy.rlib.jit import hint
 

Modified: pypy/branch/spine-of-frames/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/spine-of-frames/pypy/annotation/unaryop.py	Thu Sep 10 16:45:13 2009
@@ -2,6 +2,7 @@
 Unary operations on SomeValues.
 """
 
+from types import MethodType
 from pypy.annotation.model import \
      SomeObject, SomeInteger, SomeBool, SomeString, SomeChar, SomeList, \
      SomeDict, SomeTuple, SomeImpossibleValue, \
@@ -727,8 +728,19 @@
 
     def getattr(p, s_attr):
         assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype
-        v = getattr(p.ll_ptrtype._example(), s_attr.const)
-        return ll_to_annotation(v)
+        example = p.ll_ptrtype._example()
+        try:
+            v = example._lookup_adtmeth(s_attr.const)
+        except AttributeError:
+            v = getattr(example, s_attr.const)
+            return ll_to_annotation(v)
+        else:
+            if isinstance(v, MethodType):
+                from pypy.rpython.lltypesystem import lltype
+                ll_ptrtype = lltype.typeOf(v.im_self)
+                assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
+                return SomeLLADTMeth(ll_ptrtype, v.im_func)
+            return getbookkeeper().immutablevalue(v)
     getattr.can_only_throw = []
 
     def len(p):

Modified: pypy/branch/spine-of-frames/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/config/pypyoption.py	(original)
+++ pypy/branch/spine-of-frames/pypy/config/pypyoption.py	Thu Sep 10 16:45:13 2009
@@ -328,6 +328,9 @@
         BoolOption("getattributeshortcut",
                    "track types that override __getattribute__",
                    default=False),
+        BoolOption("newshortcut",
+                   "cache and shortcut calling __new__ from builtin types",
+                   default=False),        
 
         BoolOption("logspaceoptypes",
                    "a instrumentation option: before exit, print the types seen by "
@@ -369,6 +372,7 @@
         config.objspace.std.suggest(builtinshortcut=True)
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
+        config.objspace.std.suggest(newshortcut=True)        
 
     # extra costly optimizations only go in level 3
     if level == '3':
@@ -396,7 +400,8 @@
 
     # extra optimizations with the JIT
     if level == 'jit':
-        config.objspace.std.suggest(withsharingdict=True)
+        if type_system != 'ootype':
+            config.objspace.std.suggest(withsharingdict=True)
         config.objspace.std.suggest(withcelldict=True)
 
 

Modified: pypy/branch/spine-of-frames/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/error.py	(original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/error.py	Thu Sep 10 16:45:13 2009
@@ -262,8 +262,33 @@
     # 31: ANSI color code "red"
     ansi_print(text, esc="31", file=file, newline=newline)
 
+try:
+    WindowsError
+except NameError:
+    _WINDOWS = False
+else:
+    _WINDOWS = True
+
+    def wrap_windowserror(space, e):
+        from pypy.rlib import rwin32
+
+        winerror = e.winerror
+        try:
+            msg = rwin32.FormatError(winerror)
+        except ValueError:
+            msg = 'Windows Error %d' % winerror
+        exc = space.w_WindowsError
+        w_error = space.call_function(exc,
+                                      space.wrap(winerror),
+                                      space.wrap(msg))
+        return OperationError(exc, w_error)
+
 def wrap_oserror(space, e, exception_name='w_OSError'): 
     assert isinstance(e, OSError) 
+
+    if _WINDOWS and isinstance(e, WindowsError):
+        return wrap_windowserror(space, e)
+
     errno = e.errno
     try:
         msg = os.strerror(errno)

Modified: pypy/branch/spine-of-frames/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/function.py	(original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/function.py	Thu Sep 10 16:45:13 2009
@@ -39,11 +39,11 @@
 
     def call_args(self, args):
         # delegate activation to code        
-        return self.code.funcrun(self, args)
+        return self.getcode().funcrun(self, args)
 
     def call_obj_args(self, w_obj, args):
         # delegate activation to code
-        return self.code.funcrun_obj(self, w_obj, args)
+        return self.getcode().funcrun_obj(self, w_obj, args)
 
     def getcode(self):
         return hint(self.code, promote=True)

Modified: pypy/branch/spine-of-frames/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/pycode.py	Thu Sep 10 16:45:13 2009
@@ -184,28 +184,30 @@
         
         self.fast_natural_arity = PyCode.FLATPYCALL | self.co_argcount
 
-    @jit.dont_look_inside
     def funcrun(self, func, args):
         frame = self.space.createframe(self, func.w_func_globals,
                                   func.closure)
         sig = self._signature
         # speed hack
-        args_matched = args.parse_into_scope(None, frame.fastlocals_w,
+        fresh_frame = jit.hint(frame, access_directly=True,
+                                      fresh_virtualizable=True)
+        args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
                                              func.name,
                                              sig, func.defs_w)
-        frame.init_cells()
+        fresh_frame.init_cells()
         return frame.run()
 
-    @jit.dont_look_inside
     def funcrun_obj(self, func, w_obj, args):
         frame = self.space.createframe(self, func.w_func_globals,
                                   func.closure)
         sig = self._signature
         # speed hack
-        args_matched = args.parse_into_scope(w_obj, frame.fastlocals_w,
+        fresh_frame = jit.hint(frame, access_directly=True,
+                                      fresh_virtualizable=True)        
+        args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
                                              func.name,
                                              sig, func.defs_w)
-        frame.init_cells()
+        fresh_frame.init_cells()
         return frame.run()
 
     def getvarnames(self):

Modified: pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py	(original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py	Thu Sep 10 16:45:13 2009
@@ -641,21 +641,17 @@
     def setup_method(self, method):
         self.compiler = CPythonCompiler(self.space)
 
-    _unicode_error_kind = "w_SyntaxError"
-
-    if sys.version_info < (2, 4):
-        def skip_on_2_3(self):
-            py.test.skip("syntax not supported by the CPython 2.3 compiler")
-        test_unicodeliterals = skip_on_2_3
-        test_none_assignment = skip_on_2_3
-        test_import = skip_on_2_3
-    elif sys.version_info < (2, 5):
+    if sys.version_info < (2, 5):
         def skip_on_2_4(self):
             py.test.skip("syntax not supported by the CPython 2.4 compiler")
         _unicode_error_kind = "w_UnicodeError"
         test_continue_in_nested_finally = skip_on_2_4
         test_try_except_finally = skip_on_2_4
         test_yield_in_finally = skip_on_2_4
+    elif sys.version_info < (2, 6):
+        _unicode_error_kind = "w_UnicodeDecodeError"
+    else:
+        _unicode_error_kind = "w_SyntaxError"
 
 class TestPythonAstCompiler_25_grammar(BaseTestCompiler):
     def setup_method(self, method):

Modified: pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py	(original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py	Thu Sep 10 16:45:13 2009
@@ -374,7 +374,19 @@
         result = pickle.loads(pckl)
         raises(TypeError, len, diter)
         assert list(diter) == list(result)
-    
+
+    def test_pickle_reversed(self):
+        import pickle
+        r = reversed(tuple(range(10)))
+        r.next()
+        r.next()
+        pickled = pickle.dumps(r)
+        result = pickle.loads(pickled)
+        result.next()
+        r.next()
+        assert type(r) is type(result)
+        assert list(r) == list(result)
+
     def test_pickle_enum(self):
         import pickle
         e      = enumerate(range(10))

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py	Thu Sep 10 16:45:13 2009
@@ -8,7 +8,8 @@
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.annotation import model as annmodel
 from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr,
-                                         BoxInt, BoxPtr, BoxObj, REF)
+                                         BoxInt, BoxPtr, BoxObj, BoxFloat,
+                                         REF, INT, FLOAT)
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.module.support import LLSupport, OOSupport
@@ -82,6 +83,21 @@
     'uint_ge'         : (('int', 'int'), 'bool'),
     'uint_xor'        : (('int', 'int'), 'int'),
     'uint_rshift'     : (('int', 'int'), 'int'),
+    'float_add'       : (('float', 'float'), 'float'),
+    'float_sub'       : (('float', 'float'), 'float'),
+    'float_mul'       : (('float', 'float'), 'float'),
+    'float_truediv'   : (('float', 'float'), 'float'),
+    'float_lt'        : (('float', 'float'), 'bool'),
+    'float_le'        : (('float', 'float'), 'bool'),
+    'float_eq'        : (('float', 'float'), 'bool'),
+    'float_ne'        : (('float', 'float'), 'bool'),
+    'float_gt'        : (('float', 'float'), 'bool'),
+    'float_ge'        : (('float', 'float'), 'bool'),
+    'float_neg'       : (('float',), 'float'),
+    'float_abs'       : (('float',), 'float'),
+    'float_is_true'   : (('float',), 'bool'),
+    'cast_float_to_int':(('float',), 'int'),
+    'cast_int_to_float':(('int',), 'float'),
     'same_as'         : (('int',), 'int'),      # could also be ptr=>ptr
     'new_with_vtable' : (('ref',), 'ref'),
     'new'             : ((), 'ref'),
@@ -124,7 +140,6 @@
     'unicodegetitem'  : (('ref', 'int'), 'int'),
     'unicodesetitem'  : (('ref', 'int', 'int'), 'int'),
     'cast_ptr_to_int' : (('ref',), 'int'),
-    'cast_int_to_ptr' : (('int',), 'ref'),
     'debug_merge_point': (('ref',), None),
     #'getitem'         : (('void', 'ref', 'int'), 'int'),
     #'setitem'         : (('void', 'ref', 'int', 'int'), None),
@@ -249,6 +264,8 @@
         return str(bool(x))
     #elif tp == 'fieldname':
     #    return str(symbolic.TokenToField[x...][1])
+    elif tp == 'float':
+        return str(x)
     else:
         raise NotImplementedError("tp = %s" % tp)
 
@@ -259,14 +276,10 @@
     return _to_opaque(CompiledLoop())
 
 def compile_start_int_var(loop):
-    loop = _from_opaque(loop)
-    assert not loop.operations
-    v = Variable()
-    v.concretetype = lltype.Signed
-    loop.inputargs.append(v)
-    r = len(_variables)
-    _variables.append(v)
-    return r
+    return compile_start_ref_var(loop, lltype.Signed)
+
+def compile_start_float_var(loop):
+    return compile_start_ref_var(loop, lltype.Float)
 
 def compile_start_ref_var(loop, TYPE):
     loop = _from_opaque(loop)
@@ -295,11 +308,10 @@
     op.args.append(_variables[intvar])
 
 def compile_add_int_const(loop, value):
-    loop = _from_opaque(loop)
-    const = Constant(value)
-    const.concretetype = lltype.Signed
-    op = loop.operations[-1]
-    op.args.append(const)
+    compile_add_ref_const(loop, value, lltype.Signed)
+
+def compile_add_float_const(loop, value):
+    compile_add_ref_const(loop, value, lltype.Float)
 
 def compile_add_ref_const(loop, value, TYPE):
     loop = _from_opaque(loop)
@@ -309,14 +321,10 @@
     op.args.append(const)
 
 def compile_add_int_result(loop):
-    loop = _from_opaque(loop)
-    v = Variable()
-    v.concretetype = lltype.Signed
-    op = loop.operations[-1]
-    op.result = v
-    r = len(_variables)
-    _variables.append(v)
-    return r
+    return compile_add_ref_result(loop, lltype.Signed)
+
+def compile_add_float_result(loop):
+    return compile_add_ref_result(loop, lltype.Float)
 
 def compile_add_ref_result(loop, TYPE):
     loop = _from_opaque(loop)
@@ -411,6 +419,8 @@
                         x = self.as_ptr(result)
                     elif RESTYPE is ootype.Object:
                         x = self.as_object(result)
+                    elif RESTYPE is lltype.Float:
+                        x = self.as_float(result)
                     else:
                         raise Exception("op.result.concretetype is %r"
                                         % (RESTYPE,))
@@ -473,6 +483,9 @@
     def as_object(self, x):
         return ootype.cast_to_object(x)
 
+    def as_float(self, x):
+        return cast_to_float(x)
+
     def log_progress(self):
         count = sum(_stats.exec_counters.values())
         count_jumps = _stats.exec_jumps
@@ -501,6 +514,8 @@
                     for x in args:
                         if type(x) is int:
                             boxedargs.append(BoxInt(x))
+                        elif type(x) is float:
+                            boxedargs.append(BoxFloat(x))
                         elif isinstance(ootype.typeOf(x), ootype.OOType):
                             boxedargs.append(BoxObj(ootype.cast_to_object(x)))
                         else:
@@ -617,24 +632,36 @@
     def op_getarrayitem_gc(self, arraydescr, array, index):
         if arraydescr.typeinfo == REF:
             return do_getarrayitem_gc_ptr(array, index)
-        else:
+        elif arraydescr.typeinfo == INT:
             return do_getarrayitem_gc_int(array, index, self.memocast)
+        elif arraydescr.typeinfo == FLOAT:
+            return do_getarrayitem_gc_float(array, index)
+        else:
+            raise NotImplementedError
 
     op_getarrayitem_gc_pure = op_getarrayitem_gc
 
     def op_getfield_gc(self, fielddescr, struct):
         if fielddescr.typeinfo == REF:
             return do_getfield_gc_ptr(struct, fielddescr.ofs)
-        else:
+        elif fielddescr.typeinfo == INT:
             return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast)
+        elif fielddescr.typeinfo == FLOAT:
+            return do_getfield_gc_float(struct, fielddescr.ofs)
+        else:
+            raise NotImplementedError
 
     op_getfield_gc_pure = op_getfield_gc
 
     def op_getfield_raw(self, fielddescr, struct):
         if fielddescr.typeinfo == REF:
             return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast)
-        else:
+        elif fielddescr.typeinfo == INT:
             return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast)
+        elif fielddescr.typeinfo == FLOAT:
+            return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast)
+        else:
+            raise NotImplementedError
 
     def op_new(self, size):
         return do_new(size.ofs)
@@ -650,23 +677,36 @@
     def op_setarrayitem_gc(self, arraydescr, array, index, newvalue):
         if arraydescr.typeinfo == REF:
             do_setarrayitem_gc_ptr(array, index, newvalue)
-        else:
+        elif arraydescr.typeinfo == INT:
             do_setarrayitem_gc_int(array, index, newvalue, self.memocast)
+        elif arraydescr.typeinfo == FLOAT:
+            do_setarrayitem_gc_float(array, index, newvalue)
+        else:
+            raise NotImplementedError
 
     def op_setfield_gc(self, fielddescr, struct, newvalue):
         if fielddescr.typeinfo == REF:
             do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
-        else:
+        elif fielddescr.typeinfo == INT:
             do_setfield_gc_int(struct, fielddescr.ofs, newvalue,
                                self.memocast)
+        elif fielddescr.typeinfo == FLOAT:
+            do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
+        else:
+            raise NotImplementedError
 
     def op_setfield_raw(self, fielddescr, struct, newvalue):
         if fielddescr.typeinfo == REF:
             do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue,
                                 self.memocast)
-        else:
+        elif fielddescr.typeinfo == INT:
             do_setfield_raw_int(struct, fielddescr.ofs, newvalue,
                                 self.memocast)
+        elif fielddescr.typeinfo == FLOAT:
+            do_setfield_raw_float(struct, fielddescr.ofs, newvalue,
+                                  self.memocast)
+        else:
+            raise NotImplementedError
 
     def op_call(self, calldescr, func, *args):
         _call_args[:] = args
@@ -674,9 +714,12 @@
             err_result = None
         elif calldescr.typeinfo == REF:
             err_result = lltype.nullptr(llmemory.GCREF.TO)
-        else:
-            assert calldescr.typeinfo == 'i'
+        elif calldescr.typeinfo == INT:
             err_result = 0
+        elif calldescr.typeinfo == FLOAT:
+            err_result = 0.0
+        else:
+            raise NotImplementedError
         return _do_call_common(func, self.memocast, err_result)
 
     op_call_pure = op_call
@@ -696,9 +739,6 @@
     def op_cast_ptr_to_int(self, descr, ptr):
         return cast_to_int(ptr, self.memocast)
 
-    def op_cast_int_to_ptr(self, descr, val):
-        return cast_from_int(llmemory.GCREF, val, self.memocast)
-
     def op_uint_xor(self, descr, arg1, arg2):
         return arg1 ^ arg2
 
@@ -735,6 +775,8 @@
         obj = ootype.cast_from_object(TYPE, obj)
         if isinstance(ootype.typeOf(newvalue), ootype.OOType):
             newvalue = ootype.cast_from_object(T, newvalue)
+        elif isinstance(T, lltype.Primitive):
+            newvalue = lltype.cast_primitive(T, newvalue)
         setattr(obj, fieldname, newvalue)
 
     def op_getarrayitem_gc(self, typedescr, obj, index):
@@ -834,6 +876,15 @@
 def cast_from_ptr(TYPE, x):
     return lltype.cast_opaque_ptr(TYPE, x)
 
+def cast_to_float(x):      # not really a cast, just a type check
+    assert isinstance(x, float)
+    return x
+
+def cast_from_float(TYPE, x):   # not really a cast, just a type check
+    assert TYPE is lltype.Float
+    assert isinstance(x, float)
+    return x
+
 
 def new_frame(memocast, is_oo):
     if is_oo:
@@ -857,9 +908,10 @@
     del _future_values[:]
 
 def set_future_value_int(index, value):
-    del _future_values[index:]
-    assert len(_future_values) == index
-    _future_values.append(value)
+    set_future_value_ref(index, value)
+
+def set_future_value_float(index, value):
+    set_future_value_ref(index, value)
 
 def set_future_value_ref(index, value):
     del _future_values[index:]
@@ -890,6 +942,10 @@
     frame = _from_opaque(frame)
     return frame.fail_args[num]
 
+def frame_float_getvalue(frame, num):
+    frame = _from_opaque(frame)
+    return frame.fail_args[num]
+
 def frame_ptr_getvalue(frame, num):
     frame = _from_opaque(frame)
     result = frame.fail_args[num]
@@ -1013,33 +1069,41 @@
     array = array._obj.container
     return cast_to_int(array.getitem(index), memocast)
 
+def do_getarrayitem_gc_float(array, index):
+    array = array._obj.container
+    return cast_to_float(array.getitem(index))
+
 def do_getarrayitem_gc_ptr(array, index):
     array = array._obj.container
     return cast_to_ptr(array.getitem(index))
 
-def do_getfield_gc_int(struct, fieldnum, memocast):
+def _getfield_gc(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    x = getattr(ptr, fieldname)
-    return cast_to_int(x, memocast)
+    return getattr(ptr, fieldname)
+
+def do_getfield_gc_int(struct, fieldnum, memocast):
+    return cast_to_int(_getfield_gc(struct, fieldnum), memocast)
+
+def do_getfield_gc_float(struct, fieldnum):
+    return cast_to_float(_getfield_gc(struct, fieldnum))
 
 def do_getfield_gc_ptr(struct, fieldnum):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    x = getattr(ptr, fieldname)
-    return cast_to_ptr(x)
+    return cast_to_ptr(_getfield_gc(struct, fieldnum))
 
-def do_getfield_raw_int(struct, fieldnum, memocast):
+def _getfield_raw(struct, fieldnum, memocast):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
-    x = getattr(ptr, fieldname)
-    return cast_to_int(x, memocast)
+    return getattr(ptr, fieldname)
+
+def do_getfield_raw_int(struct, fieldnum, memocast):
+    return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast)
+
+def do_getfield_raw_float(struct, fieldnum, memocast):
+    return cast_to_float(_getfield_raw(struct, fieldnum, memocast))
 
 def do_getfield_raw_ptr(struct, fieldnum, memocast):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
-    x = getattr(ptr, fieldname)
-    return cast_to_ptr(x)
+    return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast))
 
 def do_new(size):
     TYPE = symbolic.Size2Type[size]
@@ -1057,6 +1121,12 @@
     newvalue = cast_from_int(ITEMTYPE, newvalue, memocast)
     array.setitem(index, newvalue)
 
+def do_setarrayitem_gc_float(array, index, newvalue):
+    array = array._obj.container
+    ITEMTYPE = lltype.typeOf(array).OF
+    newvalue = cast_from_float(ITEMTYPE, newvalue)
+    array.setitem(index, newvalue)
+
 def do_setarrayitem_gc_ptr(array, index, newvalue):
     array = array._obj.container
     ITEMTYPE = lltype.typeOf(array).OF
@@ -1070,6 +1140,13 @@
     newvalue = cast_from_int(FIELDTYPE, newvalue, memocast)
     setattr(ptr, fieldname, newvalue)
 
+def do_setfield_gc_float(struct, fieldnum, newvalue):
+    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
+    FIELDTYPE = getattr(STRUCT, fieldname)
+    newvalue = cast_from_float(FIELDTYPE, newvalue)
+    setattr(ptr, fieldname, newvalue)
+
 def do_setfield_gc_ptr(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
@@ -1084,6 +1161,13 @@
     newvalue = cast_from_int(FIELDTYPE, newvalue, memocast)
     setattr(ptr, fieldname, newvalue)
 
+def do_setfield_raw_float(struct, fieldnum, newvalue, memocast):
+    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+    ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
+    FIELDTYPE = getattr(STRUCT, fieldname)
+    newvalue = cast_from_float(FIELDTYPE, newvalue)
+    setattr(ptr, fieldname, newvalue)
+
 def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
@@ -1113,6 +1197,9 @@
 def do_call_pushint(x):
     _call_args.append(x)
 
+def do_call_pushfloat(x):
+    _call_args.append(x)
+
 def do_call_pushptr(x):
     _call_args.append(x)
 
@@ -1143,6 +1230,10 @@
     x = _do_call_common(f, memocast, 0)
     return cast_to_int(x, memocast)
 
+def do_call_float(f, memocast):
+    x = _do_call_common(f, memocast, 0)
+    return cast_to_float(x)
+
 def do_call_ptr(f, memocast):
     x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO))
     return cast_to_ptr(x)
@@ -1159,6 +1250,8 @@
                 x = ootype.cast_from_object(TYPE, x)
             elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
                 x = cast_from_ptr(TYPE, x)
+            elif TYPE is lltype.Float:
+                x = cast_from_float(TYPE, x)
             else:
                 x = cast_from_int(TYPE, x, memocast)
         args.append(x)
@@ -1175,15 +1268,15 @@
     else:
         mymethod = meth
         myargs = args
-    if hasattr(mymethod, 'graph'):
-        llinterp = _llinterp      # it's a global set here by CPU.__init__()
-        try:
+    try:
+        if hasattr(mymethod, 'graph'):
+            llinterp = _llinterp      # it's a global set here by CPU.__init__()
             result = llinterp.eval_graph(mymethod.graph, myargs)
-        except LLException, e:
-            _last_exception = e
-            result = get_err_result_for_type(mymethod._TYPE.RESULT)
-    else:
-        result = meth(*args)  # no exception support in this case
+        else:
+            result = meth(*args)
+    except LLException, e:
+        _last_exception = e
+        result = get_err_result_for_type(mymethod._TYPE.RESULT)
     return result
 
 def get_err_result_for_type(T):
@@ -1248,13 +1341,16 @@
 setannotation(compile_start, s_CompiledLoop)
 setannotation(compile_start_int_var, annmodel.SomeInteger())
 setannotation(compile_start_ref_var, annmodel.SomeInteger())
+setannotation(compile_start_float_var, annmodel.SomeInteger())
 setannotation(compile_add, annmodel.s_None)
 setannotation(compile_add_descr, annmodel.s_None)
 setannotation(compile_add_var, annmodel.s_None)
 setannotation(compile_add_int_const, annmodel.s_None)
 setannotation(compile_add_ref_const, annmodel.s_None)
+setannotation(compile_add_float_const, annmodel.s_None)
 setannotation(compile_add_int_result, annmodel.SomeInteger())
 setannotation(compile_add_ref_result, annmodel.SomeInteger())
+setannotation(compile_add_float_result, annmodel.SomeInteger())
 setannotation(compile_add_jump_target, annmodel.s_None)
 setannotation(compile_add_fail, annmodel.s_None)
 setannotation(compile_suboperations, s_CompiledLoop)
@@ -1264,9 +1360,11 @@
 setannotation(frame_clear, annmodel.s_None)
 setannotation(set_future_value_int, annmodel.s_None)
 setannotation(set_future_value_ref, annmodel.s_None)
+setannotation(set_future_value_float, annmodel.s_None)
 setannotation(frame_execute, annmodel.SomeInteger())
 setannotation(frame_int_getvalue, annmodel.SomeInteger())
 setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF))
+setannotation(frame_float_getvalue, annmodel.SomeFloat())
 
 setannotation(get_exception, annmodel.SomeAddress())
 setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF))
@@ -1288,18 +1386,24 @@
 setannotation(do_unicodegetitem, annmodel.SomeInteger())
 setannotation(do_getarrayitem_gc_int, annmodel.SomeInteger())
 setannotation(do_getarrayitem_gc_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getarrayitem_gc_float, annmodel.SomeFloat())
 setannotation(do_getfield_gc_int, annmodel.SomeInteger())
 setannotation(do_getfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getfield_gc_float, annmodel.SomeFloat())
 setannotation(do_getfield_raw_int, annmodel.SomeInteger())
 setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getfield_raw_float, annmodel.SomeFloat())
 setannotation(do_new, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_new_array, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_setarrayitem_gc_int, annmodel.s_None)
 setannotation(do_setarrayitem_gc_ptr, annmodel.s_None)
+setannotation(do_setarrayitem_gc_float, annmodel.s_None)
 setannotation(do_setfield_gc_int, annmodel.s_None)
 setannotation(do_setfield_gc_ptr, annmodel.s_None)
+setannotation(do_setfield_gc_float, annmodel.s_None)
 setannotation(do_setfield_raw_int, annmodel.s_None)
 setannotation(do_setfield_raw_ptr, annmodel.s_None)
+setannotation(do_setfield_raw_float, annmodel.s_None)
 setannotation(do_newstr, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_strsetitem, annmodel.s_None)
 setannotation(do_newunicode, annmodel.SomePtr(llmemory.GCREF))
@@ -1308,4 +1412,5 @@
 setannotation(do_call_pushptr, annmodel.s_None)
 setannotation(do_call_int, annmodel.SomeInteger())
 setannotation(do_call_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_call_float, annmodel.SomeFloat())
 setannotation(do_call_void, annmodel.s_None)

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py	Thu Sep 10 16:45:13 2009
@@ -8,7 +8,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.jit.metainterp import history
-from pypy.jit.metainterp.history import REF
+from pypy.jit.metainterp.history import REF, INT, FLOAT
 from pypy.jit.metainterp.warmspot import unwrap
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.backend import model
@@ -74,6 +74,7 @@
 
 
 class BaseCPU(model.AbstractCPU):
+    supports_floats = True
 
     def __init__(self, rtyper, stats=None, translate_support_code=False,
                  annmixlevel=None, gcdescr=None):
@@ -118,6 +119,8 @@
             elif isinstance(box, self.ts.BoxRef):
                 TYPE = self.ts.BASETYPE
                 var2index[box] = llimpl.compile_start_ref_var(c, TYPE)
+            elif isinstance(box, history.BoxFloat):
+                var2index[box] = llimpl.compile_start_float_var(c)
             else:
                 raise Exception("box is: %r" % (box,))
         self._compile_branch(c, loop.operations, var2index)
@@ -144,6 +147,8 @@
                     llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE)
                 elif isinstance(x, history.ConstAddr):
                     llimpl.compile_add_int_const(c, x.getint())
+                elif isinstance(x, history.ConstFloat):
+                    llimpl.compile_add_float_const(c, x.value)
                 else:
                     raise Exception("%s args contain: %r" % (op.getopname(),
                                                              x))
@@ -156,6 +161,8 @@
                     var2index[x] = llimpl.compile_add_int_result(c)
                 elif isinstance(x, self.ts.BoxRef):
                     var2index[x] = llimpl.compile_add_ref_result(c, self.ts.BASETYPE)
+                elif isinstance(x, history.BoxFloat):
+                    var2index[x] = llimpl.compile_add_float_result(c)
                 else:
                     raise Exception("%s.result contain: %r" % (op.getopname(),
                                                                x))
@@ -186,12 +193,18 @@
     def set_future_value_ref(self, index, objvalue):
         llimpl.set_future_value_ref(index, objvalue)
 
+    def set_future_value_float(self, index, floatvalue):
+        llimpl.set_future_value_float(index, floatvalue)
+
     def get_latest_value_int(self, index):
         return llimpl.frame_int_getvalue(self.latest_frame, index)
 
     def get_latest_value_ref(self, index):
         return llimpl.frame_ptr_getvalue(self.latest_frame, index)
 
+    def get_latest_value_float(self, index):
+        return llimpl.frame_float_getvalue(self.latest_frame, index)
+
     # ----------
 
     def get_exception(self):
@@ -228,6 +241,9 @@
     def cast_int_to_adr(self, int):
         return llimpl.cast_int_to_adr(self.memo_cast, int)
 
+    def cast_gcref_to_int(self, gcref):
+        return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref))
+
 
 
 class LLtypeCPU(BaseCPU):
@@ -299,9 +315,14 @@
         index = args[1].getint()
         if arraydescr.typeinfo == REF:
             return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index))
-        else:
+        elif arraydescr.typeinfo == INT:
             return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index,
                                                                self.memo_cast))
+        elif arraydescr.typeinfo == FLOAT:
+            return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array,
+                                                                    index))
+        else:
+            raise NotImplementedError
 
     def do_getfield_gc(self, args, fielddescr):
         assert isinstance(fielddescr, Descr)
@@ -309,10 +330,16 @@
         if fielddescr.typeinfo == REF:
             return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct,
                                                             fielddescr.ofs))
-        else:
+        elif fielddescr.typeinfo == INT:
             return history.BoxInt(llimpl.do_getfield_gc_int(struct,
                                                             fielddescr.ofs,
                                                             self.memo_cast))
+        elif fielddescr.typeinfo == FLOAT:
+            return history.BoxFloat(llimpl.do_getfield_gc_float(struct,
+                                                            fielddescr.ofs))
+        else:
+            raise NotImplementedError
+
     def do_getfield_raw(self, args, fielddescr):
         assert isinstance(fielddescr, Descr)
         struct = self.cast_int_to_adr(args[0].getint())
@@ -320,10 +347,16 @@
             return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct,
                                                              fielddescr.ofs,
                                                              self.memo_cast))
-        else:
+        elif fielddescr.typeinfo == INT:
             return history.BoxInt(llimpl.do_getfield_raw_int(struct,
                                                              fielddescr.ofs,
                                                              self.memo_cast))
+        elif fielddescr.typeinfo == FLOAT:
+            return history.BoxFloat(llimpl.do_getfield_raw_float(struct,
+                                                             fielddescr.ofs,
+                                                             self.memo_cast))
+        else:
+            raise NotImplementedError
 
     def do_new(self, args, size):
         assert isinstance(size, Descr)
@@ -350,10 +383,15 @@
         if arraydescr.typeinfo == REF:
             newvalue = args[2].getref_base()
             llimpl.do_setarrayitem_gc_ptr(array, index, newvalue)
-        else:
+        elif arraydescr.typeinfo == INT:
             newvalue = args[2].getint()
             llimpl.do_setarrayitem_gc_int(array, index, newvalue,
                                           self.memo_cast)
+        elif arraydescr.typeinfo == FLOAT:
+            newvalue = args[2].getfloat()
+            llimpl.do_setarrayitem_gc_float(array, index, newvalue)
+        else:
+            raise NotImplementedError
 
     def do_setfield_gc(self, args, fielddescr):
         assert isinstance(fielddescr, Descr)
@@ -361,10 +399,15 @@
         if fielddescr.typeinfo == REF:
             newvalue = args[1].getref_base()
             llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
-        else:
+        elif fielddescr.typeinfo == INT:
             newvalue = args[1].getint()
             llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue,
                                       self.memo_cast)
+        elif fielddescr.typeinfo == FLOAT:
+            newvalue = args[1].getfloat()
+            llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
+        else:
+            raise NotImplementedError
 
     def do_setfield_raw(self, args, fielddescr):
         assert isinstance(fielddescr, Descr)
@@ -373,10 +416,16 @@
             newvalue = args[1].getref_base()
             llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue,
                                        self.memo_cast)
-        else:
+        elif fielddescr.typeinfo == INT:
             newvalue = args[1].getint()
             llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue,
                                        self.memo_cast)
+        elif fielddescr.typeinfo == FLOAT:
+            newvalue = args[1].getfloat()
+            llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue,
+                                         self.memo_cast)
+        else:
+            raise NotImplementedError
 
     def do_same_as(self, args, descr=None):
         return args[0].clonebox()
@@ -416,16 +465,14 @@
                 llimpl.do_call_pushint(arg.getint())
         if calldescr.typeinfo == REF:
             return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast))
-        elif calldescr.typeinfo == 'i':
+        elif calldescr.typeinfo == INT:
             return history.BoxInt(llimpl.do_call_int(func, self.memo_cast))
-        else:  # calldescr.typeinfo == 'v'  # void
+        elif calldescr.typeinfo == FLOAT:
+            return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast))
+        elif calldescr.typeinfo == 'v':  # void
             llimpl.do_call_void(func, self.memo_cast)
-
-    def do_cast_int_to_ptr(self, args, descr=None):
-        assert descr is None
-        return history.BoxPtr(llimpl.cast_from_int(llmemory.GCREF,
-                                                   args[0].getint(),
-                                                   self.memo_cast))
+        else:
+            raise NotImplementedError
 
     def do_cast_ptr_to_int(self, args, descr=None):
         assert descr is None
@@ -573,6 +620,8 @@
 def boxresult(RESULT, result):
     if isinstance(RESULT, ootype.OOType):
         return history.BoxObj(ootype.cast_to_object(result))
+    elif RESULT is lltype.Float:
+        return history.BoxFloat(result)
     else:
         return history.BoxInt(lltype.cast_primitive(ootype.Signed, result))
 boxresult._annspecialcase_ = 'specialize:arg(0)'

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py	Thu Sep 10 16:45:13 2009
@@ -343,7 +343,7 @@
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 type_id, num_elem, self.array_basesize, itemsize,
-                self.array_length_ofs, True, False)
+                self.array_length_ofs, True)
         self.malloc_array = malloc_array
         self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType(
             [lltype.Signed] * 3, llmemory.GCREF))
@@ -359,12 +359,12 @@
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 str_type_id, length, str_basesize, str_itemsize,
-                str_ofs_length, True, False)
+                str_ofs_length, True)
         def malloc_unicode(length):
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 unicode_type_id, length, unicode_basesize, unicode_itemsize,
-                unicode_ofs_length, True, False)
+                unicode_ofs_length, True)
         self.malloc_str = malloc_str
         self.malloc_unicode = malloc_unicode
         self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py	Thu Sep 10 16:45:13 2009
@@ -1,8 +1,10 @@
 import sys
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values
-from pypy.jit.metainterp.typesystem import llhelper
 from pypy.jit.backend.model import AbstractCPU
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
@@ -19,7 +21,7 @@
 
 
 class AbstractLLCPU(AbstractCPU):
-    ts = llhelper
+    from pypy.jit.metainterp.typesystem import llhelper as ts
 
     def __init__(self, rtyper, stats, translate_support_code=False,
                  gcdescr=None):
@@ -37,6 +39,11 @@
                                                         translate_support_code)
         self._setup_prebuilt_error('ovf', OverflowError)
         self._setup_prebuilt_error('zer', ZeroDivisionError)
+        if translate_support_code:
+            self._setup_exception_handling_translated()
+        else:
+            self._setup_exception_handling_untranslated()
+        self.clear_exception()
 
     def set_class_sizes(self, class_sizes):
         self.class_sizes = class_sizes
@@ -54,13 +61,99 @@
                                             immortal=True)
         setattr(self, '_%s_error_vtable' % prefix,
                 llmemory.cast_ptr_to_adr(ll_inst.typeptr))
-        setattr(self, '_%s_error_inst' % prefix,
-                llmemory.cast_ptr_to_adr(ll_inst))
+        setattr(self, '_%s_error_inst' % prefix, ll_inst)
+
+
+    def _setup_exception_handling_untranslated(self):
+        # for running un-translated only, all exceptions occurring in the
+        # llinterpreter are stored in '_exception_emulator', which is then
+        # read back by the machine code reading at the address given by
+        # pos_exception() and pos_exc_value().
+        _exception_emulator = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+                                            zero=True, flavor='raw')
+        self._exception_emulator = _exception_emulator
+
+        def _store_exception(lle):
+            self._last_exception = lle       # keepalive
+            tp_i = rffi.cast(lltype.Signed, lle.args[0])
+            v_i = rffi.cast(lltype.Signed, lle.args[1])
+            _exception_emulator[0] = tp_i
+            _exception_emulator[1] = v_i
+
+        self.debug_ll_interpreter = LLInterpreter(self.rtyper)
+        self.debug_ll_interpreter._store_exception = _store_exception
+
+        def pos_exception():
+            return rffi.cast(lltype.Signed, _exception_emulator)
+
+        def pos_exc_value():
+            return (rffi.cast(lltype.Signed, _exception_emulator) +
+                    rffi.sizeof(lltype.Signed))
+
+        def save_exception():
+            # copy from _exception_emulator to the real attributes on self
+            tp_i = _exception_emulator[0]
+            v_i  = _exception_emulator[1]
+            _exception_emulator[0] = 0
+            _exception_emulator[1] = 0
+            self.saved_exception = tp_i
+            self.saved_exc_value = self._cast_int_to_gcref(v_i)
+
+        self.pos_exception = pos_exception
+        self.pos_exc_value = pos_exc_value
+        self.save_exception = save_exception
+
+
+    def _setup_exception_handling_translated(self):
+
+        def pos_exception():
+            addr = llop.get_exception_addr(llmemory.Address)
+            return llmemory.cast_adr_to_int(addr)
+
+        def pos_exc_value():
+            addr = llop.get_exc_value_addr(llmemory.Address)
+            return llmemory.cast_adr_to_int(addr)
+
+        def save_exception():
+            addr = llop.get_exception_addr(llmemory.Address)
+            exception = rffi.cast(lltype.Signed, addr.address[0])
+            addr.address[0] = llmemory.NULL
+            addr = llop.get_exc_value_addr(llmemory.Address)
+            exc_value = rffi.cast(llmemory.GCREF, addr.address[0])
+            addr.address[0] = llmemory.NULL
+            # from now on, the state is again consistent -- no more RPython
+            # exception is set.  The following code produces a write barrier
+            # in the assignment to self.saved_exc_value, as needed.
+            self.saved_exception = exception
+            self.saved_exc_value = exc_value
+
+        self.pos_exception = pos_exception
+        self.pos_exc_value = pos_exc_value
+        self.save_exception = save_exception
+
+    _SAVE_EXCEPTION_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
+
+    def get_save_exception_int(self):
+        f = llhelper(self._SAVE_EXCEPTION_FUNC, self.save_exception)
+        return rffi.cast(lltype.Signed, f)
+
+    def get_exception(self):
+        return self.saved_exception
+
+    def get_exc_value(self):
+        return self.saved_exc_value
+
+    def clear_exception(self):
+        self.saved_exception = 0
+        self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
+
 
     # ------------------- helpers and descriptions --------------------
 
     @staticmethod
-    def cast_int_to_gcref(x):
+    def _cast_int_to_gcref(x):
+        # dangerous!  only use if you are sure no collection could occur
+        # between reading the integer and casting it to a pointer
         if not we_are_translated():
             _check_addr_range(x)
         return rffi.cast(llmemory.GCREF, x)
@@ -109,14 +202,14 @@
 
     def get_overflow_error(self):
         ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
-        ovf_inst = self.cast_int_to_gcref(
-            self.cast_adr_to_int(self._ovf_error_inst))
+        ovf_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                          self._ovf_error_inst)
         return ovf_vtable, ovf_inst
 
     def get_zero_division_error(self):
         zer_vtable = self.cast_adr_to_int(self._zer_error_vtable)
-        zer_inst = self.cast_int_to_gcref(
-            self.cast_adr_to_int(self._zer_error_inst))
+        zer_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                          self._zer_error_inst)
         return zer_vtable, zer_inst
 
     # ____________________________________________________________
@@ -142,7 +235,7 @@
         else:
             raise NotImplementedError("size = %d" % size)
         if ptr:
-            return BoxPtr(self.cast_int_to_gcref(val))
+            return BoxPtr(self._cast_int_to_gcref(val))
         else:
             return BoxInt(val)
 
@@ -207,7 +300,7 @@
         else:
             raise NotImplementedError("size = %d" % size)
         if ptr:
-            return BoxPtr(self.cast_int_to_gcref(val))
+            return BoxPtr(self._cast_int_to_gcref(val))
         else:
             return BoxInt(val)
 
@@ -311,9 +404,6 @@
     def do_cast_ptr_to_int(self, args, descr=None):
         return BoxInt(self.cast_gcref_to_int(args[0].getref_base()))
 
-    def do_cast_int_to_ptr(self, args, descr=None):
-        return BoxPtr(self.cast_int_to_gcref(args[0].getint()))
-
 
 import pypy.jit.metainterp.executor
 pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU)

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py	Thu Sep 10 16:45:13 2009
@@ -124,10 +124,8 @@
         return p
 
     def do_malloc_varsize_clear(self, RESTYPE, type_id, length, size,
-                                itemsize, offset_to_length, can_collect,
-                                has_finalizer):
+                                itemsize, offset_to_length, can_collect):
         assert can_collect
-        assert not has_finalizer
         p = llmemory.raw_malloc(size + itemsize * length)
         (p + offset_to_length).signed[0] = length
         p = llmemory.cast_adr_to_ptr(p, RESTYPE)

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/model.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/model.py	Thu Sep 10 16:45:13 2009
@@ -1,4 +1,5 @@
 class AbstractCPU(object):
+    supports_floats = False
 
     def set_class_sizes(self, class_sizes):
         self.class_sizes = class_sizes
@@ -160,9 +161,6 @@
     def do_cond_call_gc_malloc(self, args, calldescr):
         xxx
 
-    def do_cast_int_to_ptr(self, args, descr=None):
-        raise NotImplementedError
-
     def do_cast_ptr_to_int(self, args, descr=None):
         raise NotImplementedError
 

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py	Thu Sep 10 16:45:13 2009
@@ -1,8 +1,8 @@
 
 import py, sys, random
 from pypy.jit.metainterp.history import (BoxInt, Box, BoxPtr, TreeLoop,
-                                         ConstInt, ConstPtr, BoxObj,
-                                         ConstObj)
+                                         ConstInt, ConstPtr, BoxObj, Const,
+                                         ConstObj, BoxFloat, ConstFloat)
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.typesystem import deref
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
@@ -26,6 +26,11 @@
             elif isinstance(box, (BoxPtr, BoxObj)):
                 self.cpu.set_future_value_ref(j, box.getref_base())
                 j += 1
+            elif isinstance(box, BoxFloat):
+                self.cpu.set_future_value_float(j, box.getfloat())
+                j += 1
+            else:
+                assert isinstance(box, Const)
         res = self.cpu.execute_operations(loop)
         if res is loop.operations[-1]:
             self.guard_failed = False
@@ -35,6 +40,8 @@
             return BoxInt(self.cpu.get_latest_value_int(0))
         elif result_type == 'ref':
             return BoxPtr(self.cpu.get_latest_value_ref(0))
+        elif result_type == 'float':
+            return BoxFloat(self.cpu.get_latest_value_float(0))
         elif result_type == 'void':
             return None
         else:
@@ -48,6 +55,8 @@
             result = BoxInt()
         elif result_type == 'ref':
             result = BoxPtr()
+        elif result_type == 'float':
+            result = BoxFloat()
         else:
             raise ValueError(result_type)
         if result is None:
@@ -210,6 +219,19 @@
                                              'int')
                 assert res.value == y
 
+    def test_float_operations(self):
+        from pypy.jit.metainterp.test.test_executor import get_float_tests
+        for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
+            if len(boxargs) == 2:
+                args_variants = [(boxargs[0], boxargs[1]),
+                                 (boxargs[0], boxargs[1].constbox()),
+                                 (boxargs[0].constbox(), boxargs[1])]
+            else:
+                args_variants = [boxargs]
+            for argboxes in args_variants:
+                res = self.execute_operation(opnum, argboxes, rettype)
+                assert res.value == retvalue
+
     def test_ovf_operations(self, reversed=False):
         minint = -sys.maxint-1
         boom = 'boom'
@@ -620,14 +642,10 @@
         x = lltype.cast_opaque_ptr(llmemory.GCREF, x)
         res = self.execute_operation(rop.CAST_PTR_TO_INT,
                                      [BoxPtr(x)],  'int').value
-        res2 = self.execute_operation(rop.CAST_INT_TO_PTR,
-                                      [BoxInt(res)], 'ref').value
-        x = lltype.cast_opaque_ptr(llmemory.GCREF, x)
+        assert res == self.cpu.cast_gcref_to_int(x)
         res = self.execute_operation(rop.CAST_PTR_TO_INT,
                                      [ConstPtr(x)],  'int').value
-        res2 = self.execute_operation(rop.CAST_INT_TO_PTR,
-                                      [ConstInt(res)], 'ref').value
-        assert res2 == x
+        assert res == self.cpu.cast_gcref_to_int(x)
 
     def test_ooops_non_gc(self):
         x = lltype.malloc(lltype.Struct('x'), flavor='raw')
@@ -851,9 +869,7 @@
         x = cpu.do_newstr([BoxInt(5)])
         y = cpu.do_cast_ptr_to_int([x])
         assert isinstance(y, BoxInt)
-        z = cpu.do_cast_int_to_ptr([y])
-        assert isinstance(z, BoxPtr)
-        assert z.value == x.value
+        assert y.value == cpu.cast_gcref_to_int(x.value)
 
     def test_sorting_of_fields(self):
         S = self.S

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py	Thu Sep 10 16:45:13 2009
@@ -502,6 +502,7 @@
         bridge_builder = self.builder.fork(self.builder.cpu, subloop,
                                            op.args[:])
         self.generate_ops(bridge_builder, r, subloop, op.args[:])
+        dont_compile = False
         if r.random() < 0.1:
             subset = bridge_builder.subset_of_intvars(r)
             if len(subset) == 0:
@@ -517,17 +518,22 @@
             if self.guard_op is None:
                 guard_op.suboperations[-1] = jump_op
             else:
+                self.guard_op.suboperations[0].args.extend(subset)
+                self.builder.cpu.compile_operations(self.loop, guard_op)
                 if self.guard_op.is_guard_exception():
                     # exception clearing
                     self.guard_op.suboperations.insert(-1, exc_handling(
                         self.guard_op))
                 self.guard_op.suboperations[-1] = jump_op
+                self.builder.cpu.compile_operations(self.loop, self.guard_op)
+                dont_compile = True
             self.guard_op = jump_target.guard_op
             self.prebuilt_ptr_consts += jump_target.prebuilt_ptr_consts
             self.dont_generate_more = True
         if r.random() < .05:
             return False
-        self.builder.cpu.compile_operations(self.loop)
+        if not dont_compile:
+            self.builder.cpu.compile_operations(self.loop, guard_op)
         return True
 
 def check_random_function(cpu, BuilderClass, r, num=None, max=None):

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py	Thu Sep 10 16:45:13 2009
@@ -5,7 +5,6 @@
 from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory
 from pypy.rpython.lltypesystem.rclass import OBJECT
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.annotation import model as annmodel
 from pypy.tool.uid import fixid
 from pypy.jit.backend.logger import Logger
 from pypy.jit.backend.x86.regalloc import (RegAlloc, WORD, REGS, TempBox,
@@ -15,9 +14,13 @@
 from pypy.jit.backend.x86.ri386 import *
 from pypy.jit.metainterp.resoperation import rop
 
-# our calling convention - we pass three first args as edx, ecx and eax
+
+
+# our calling convention - we pass first 6 args in registers
 # and the rest stays on the stack
 
+RET_BP = 5 # ret ip + bp + bx + esi + edi = 5 words
+
 MAX_FAIL_BOXES = 1000
 if sys.platform == 'darwin':
     # darwin requires the stack to be 16 bytes aligned on calls
@@ -60,24 +63,6 @@
     if name.upper() == name:
         setattr(MachineCodeBlockWrapper, name, _new_method(name))
 
-class MachineCodeStack(object):
-    def __init__(self):
-        self.mcstack = []
-        self.counter = 0
-
-    def next_mc(self):
-        if len(self.mcstack) == self.counter:
-            mc = MachineCodeBlockWrapper()
-            self.mcstack.append(mc)
-        else:
-            mc = self.mcstack[self.counter]
-        self.counter += 1
-        return mc
-
-    def give_mc_back(self, mc):
-        mc.done()
-        assert self.mcstack[self.counter - 1] is mc
-        self.counter -= 1
 
 class Assembler386(object):
     mc = None
@@ -92,9 +77,6 @@
         self.malloc_array_func_addr = 0
         self.malloc_str_func_addr = 0
         self.malloc_unicode_func_addr = 0
-        self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed))
-        self._exception_addr = 0
-        self.mcstack = MachineCodeStack()
         self.logger = Logger(cpu.ts)
         self.fail_boxes_int = lltype.malloc(lltype.GcArray(lltype.Signed),
                                             MAX_FAIL_BOXES, zero=True)
@@ -111,22 +93,6 @@
                 lltype.direct_arrayitems(self.fail_boxes_ptr))
 
             self.logger.create_log()
-            # we generate the loop body in 'mc'
-            # 'mc2' is for guard recovery code
-            if we_are_translated():
-                addr = llop.get_exception_addr(llmemory.Address)
-                self._exception_data = llmemory.cast_adr_to_ptr(addr, rffi.CArrayPtr(lltype.Signed))
-            else:
-                self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2,
-                                                     zero=True, flavor='raw')
-            self._exception_addr = self.cpu.cast_ptr_to_int(
-                self._exception_data)
-            # a backup, in case our exception can be somehow mangled,
-            # by a handling code
-            self._exception_bck = lltype.malloc(rffi.CArray(lltype.Signed), 2,
-                                                zero=True, flavor='raw')
-            self._exception_bck_addr = self.cpu.cast_ptr_to_int(
-                self._exception_bck)
             # the address of the function called by 'new'
             gc_ll_descr = self.cpu.gc_ll_descr
             gc_ll_descr.initialize()
@@ -145,9 +111,10 @@
                 self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
                                                           ll_new_unicode)
             # done
-            self.mc2 = self.mcstack.next_mc()
-            self.mc = self.mcstack.next_mc()
-
+            # we generate the loop body in 'mc'
+            # 'mc2' is for guard recovery code
+            self.mc = MachineCodeBlockWrapper()
+            self.mc2 = MachineCodeBlockWrapper()
 
     def _compute_longest_fail_op(self, ops):
         max_so_far = 0
@@ -160,48 +127,57 @@
         assert max_so_far < MAX_FAIL_BOXES
         return max_so_far
 
-    def assemble(self, tree):
-        self.places_to_patch_framesize = []
-        self.jumps_to_look_at = []
+    def assemble_loop(self, loop):
+        self.assemble(loop, loop.operations, None)
+
+    def assemble_from_guard(self, tree, guard_op):
+        newaddr = self.assemble(tree, guard_op.suboperations, guard_op)
+        # patch the jump from original guard
+        addr = guard_op._x86_addr
+        mc = codebuf.InMemoryCodeBuilder(addr, addr + 128)
+        mc.write(packimm32(newaddr - addr - 4))
+        mc.done()
+
+    def assemble(self, tree, operations, guard_op):
         # the last operation can be 'jump', 'return' or 'guard_pause';
         # a 'jump' can either close a loop, or end a bridge to some
         # previously-compiled code.
-        self._compute_longest_fail_op(tree.operations)
+        self._compute_longest_fail_op(operations)
         self.tree = tree
         self.make_sure_mc_exists()
-        inputargs = tree.inputargs
-        self.logger.log_loop(tree)
-        regalloc = RegAlloc(self, tree, self.cpu.translate_support_code)
+        newpos = self.mc.tell()
+        regalloc = RegAlloc(self, tree, self.cpu.translate_support_code,
+                            guard_op)
         self._regalloc = regalloc
-        regalloc.walk_operations(tree)
-        self.sanitize_tree(tree.operations)
+        adr_lea = 0
+        if guard_op is None:
+            inputargs = tree.inputargs
+            self.logger.log_loop(tree)
+            regalloc.walk_operations(tree)
+        else:
+            inputargs = regalloc.inputargs
+            self.logger.log_operations(inputargs, guard_op.suboperations, {})
+            mc = self.mc._mc
+            adr_lea = mc.tell()
+            mc.LEA(esp, fixedsize_ebp_ofs(0))
+            regalloc._walk_operations(operations)
+        stack_depth = regalloc.max_stack_depth
         self.mc.done()
         self.mc2.done()
-        stack_words = regalloc.max_stack_depth
         # possibly align, e.g. for Mac OS X
-        RET_BP = 5 # ret ip + bp + bx + esi + edi = 5 words
-        stack_words = align_stack_words(stack_words+RET_BP)
-        tree._x86_stack_depth = stack_words-RET_BP        
-        for place in self.places_to_patch_framesize:
-            mc = codebuf.InMemoryCodeBuilder(place, place + 128)
-            mc.ADD(esp, imm32(tree._x86_stack_depth * WORD))
+        if guard_op is None:
+            tree._x86_stack_depth = stack_depth
+        else:
+            if not we_are_translated():
+                # for the benefit of tests
+                guard_op._x86_bridge_stack_depth = stack_depth
+            mc = codebuf.InMemoryCodeBuilder(adr_lea, adr_lea + 128)
+            
+            mc.LEA(esp, fixedsize_ebp_ofs(-(stack_depth + RET_BP - 2) * WORD))
             mc.done()
-        for op, pos in self.jumps_to_look_at:
-            if op.jump_target._x86_stack_depth != tree._x86_stack_depth:
-                tl = op.jump_target
-                self.patch_jump(pos, tl._x86_compiled, tl.arglocs, tl.arglocs,
-                                tree._x86_stack_depth, tl._x86_stack_depth)
         if we_are_translated():
             self._regalloc = None   # else keep it around for debugging
-
-    def sanitize_tree(self, operations):
-        """ Cleans up all attributes attached by regalloc and backend
-        """
-        for op in operations:
-            if op.is_guard():
-                op.inputargs = None
-                op.longevity = None
-                self.sanitize_tree(op.suboperations)
+        return newpos
 
     def assemble_bootstrap_code(self, jumpaddr, arglocs, args, framesize):
         self.make_sure_mc_exists()
@@ -272,14 +248,14 @@
     def regalloc_perform_discard(self, op, arglocs):
         genop_discard_list[op.opnum](self, op, arglocs)
 
-    def regalloc_perform_with_guard(self, op, guard_op, regalloc,
+    def regalloc_perform_with_guard(self, op, guard_op, faillocs,
                                     arglocs, resloc):
-        addr = self.implement_guard_recovery(guard_op, regalloc)
+        addr = self.implement_guard_recovery(guard_op, faillocs)
         genop_guard_list[op.opnum](self, op, guard_op, addr, arglocs,
                                    resloc)
 
-    def regalloc_perform_guard(self, op, regalloc, arglocs, resloc):
-        addr = self.implement_guard_recovery(op, regalloc)
+    def regalloc_perform_guard(self, op, faillocs, arglocs, resloc):
+        addr = self.implement_guard_recovery(op, faillocs)
         genop_guard_list[op.opnum](self, op, None, addr, arglocs,
                                    resloc)
 
@@ -339,9 +315,7 @@
         nargs = len(args)
         extra_on_stack = self.align_stack_for_call(nargs)
         for i in range(nargs-1, -1, -1):
-            arg = args[i]
-            assert not isinstance(arg, MODRM)
-            self.mc.PUSH(arg)
+            self.mc.PUSH(args[i])
         self.mc.CALL(rel32(addr))
         self.mark_gc_roots()
         self.mc.ADD(esp, imm(extra_on_stack * WORD))
@@ -444,7 +418,6 @@
 
     def genop_same_as(self, op, arglocs, resloc):
         self.mc.MOV(resloc, arglocs[0])
-    genop_cast_int_to_ptr = genop_same_as
     genop_cast_ptr_to_int = genop_same_as
 
     def genop_int_mod(self, op, arglocs, resloc):
@@ -599,40 +572,9 @@
     def make_merge_point(self, tree, locs):
         pos = self.mc.tell()
         tree._x86_compiled = pos
-        #tree.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(pos,
-        #                                                locs, stacklocs)
-
-    def patch_jump(self, old_pos, new_pos, oldlocs, newlocs, olddepth, newdepth):
-        for i in range(len(oldlocs)):
-            oldloc = oldlocs[i]
-            newloc = newlocs[i]
-            if isinstance(newloc, MODRM):
-                assert isinstance(oldloc, MODRM)
-                assert newloc.position == oldloc.position
-            else:
-                assert newloc is oldloc
-            # newlocs should be sorted in acending order, excluding the regs
-            if not we_are_translated():
-                locs = [loc.position for loc in newlocs if isinstance(loc, MODRM)]
-                assert locs == sorted(locs)
-        #
-        mc = codebuf.InMemoryCodeBuilder(old_pos, old_pos +
-                                         MachineCodeBlockWrapper.MC_SIZE)
-        mc.SUB(esp, imm(WORD * (newdepth - olddepth)))
-        mc.JMP(rel32(new_pos))
-        mc.done()
 
     def genop_discard_jump(self, op, locs):
-        targetmp = op.jump_target
-        # don't break the following code sequence!
-        mc = self.mc._mc
-        if op.jump_target is not self.tree:
-            self.jumps_to_look_at.append((op, mc.tell()))
-        mc.JMP(rel32(targetmp._x86_compiled))
-        if op.jump_target is not self.tree:
-            # Reserve 6 bytes for a possible later patch by patch_jump().
-            # Put them after the JMP by default, as it's not doing anything.
-            mc.SUB(esp, imm32(0))
+        self.mc.JMP(rel32(op.jump_target._x86_compiled))
 
     def genop_guard_guard_true(self, op, ign_1, addr, locs, ign_2):
         loc = locs[0]
@@ -640,19 +582,19 @@
         self.implement_guard(addr, op, self.mc.JZ)
 
     def genop_guard_guard_no_exception(self, op, ign_1, addr, locs, ign_2):
-        self.mc.CMP(heap(self._exception_addr), imm(0))
+        self.mc.CMP(heap(self.cpu.pos_exception()), imm(0))
         self.implement_guard(addr, op, self.mc.JNZ)
 
     def genop_guard_guard_exception(self, op, ign_1, addr, locs, resloc):
         loc = locs[0]
         loc1 = locs[1]
-        self.mc.MOV(loc1, heap(self._exception_addr))
+        self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
         self.mc.CMP(loc1, loc)
         self.implement_guard(addr, op, self.mc.JNE)
         if resloc is not None:
-            self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD)))
-        self.mc.MOV(heap(self._exception_addr), imm(0))
-        self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0))
+            self.mc.MOV(resloc, heap(self.cpu.pos_exc_value()))
+        self.mc.MOV(heap(self.cpu.pos_exception()), imm(0))
+        self.mc.MOV(heap(self.cpu.pos_exc_value()), imm(0))
 
     def genop_guard_guard_no_overflow(self, op, ign_1, addr, locs, resloc):
         self.implement_guard(addr, op, self.mc.JO)
@@ -674,27 +616,21 @@
         self.mc.CMP(mem(locs[0], offset), locs[1])
         self.implement_guard(addr, op, self.mc.JNE)
 
-    def implement_guard_recovery(self, guard_op, regalloc):
-        oldmc = self.mc
-        self.mc = self.mc2
-        self.mc2 = self.mcstack.next_mc()
-        addr = self.mc.tell()
+    def implement_guard_recovery(self, guard_op, fail_locs):
+        addr = self.mc2.tell()
         exc = (guard_op.opnum == rop.GUARD_EXCEPTION or
                guard_op.opnum == rop.GUARD_NO_EXCEPTION)
-        # XXX this is a heuristics to detect whether we're handling this
-        # exception or not. We should have a bit better interface to deal
-        # with that I fear
-        if (exc and (guard_op.suboperations[0].opnum == rop.GUARD_EXCEPTION or
-                    guard_op.suboperations[0].opnum == rop.GUARD_NO_EXCEPTION)):
-            exc = False
-        regalloc.walk_guard_ops(guard_op.inputargs, guard_op.suboperations, exc)
-        self.mcstack.give_mc_back(self.mc2)
-        self.mc2 = self.mc
-        self.mc = oldmc
+        guard_op._x86_faillocs = fail_locs
+        # XXX horrible hack that allows us to preserve order
+        #     of inputargs to bridge
+        guard_op._fail_op = guard_op.suboperations[0]
+        self.generate_failure(self.mc2, guard_op.suboperations[0], fail_locs,
+                              exc)
         return addr
 
-    def generate_failure(self, op, locs, exc):
-        pos = self.mc.tell()
+    def generate_failure(self, mc, op, locs, exc):
+        assert op.opnum == rop.FAIL
+        pos = mc.tell()
         for i in range(len(locs)):
             loc = locs[i]
             if isinstance(loc, REG):
@@ -702,7 +638,7 @@
                     base = self.fail_box_ptr_addr
                 else:
                     base = self.fail_box_int_addr
-                self.mc.MOV(addr_add(imm(base), imm(i*WORD)), loc)
+                mc.MOV(addr_add(imm(base), imm(i*WORD)), loc)
         for i in range(len(locs)):
             loc = locs[i]
             if not isinstance(loc, REG):
@@ -710,19 +646,20 @@
                     base = self.fail_box_ptr_addr
                 else:
                     base = self.fail_box_int_addr
-                self.mc.MOV(eax, loc)
-                self.mc.MOV(addr_add(imm(base), imm(i*WORD)), eax)
+                mc.MOV(eax, loc)
+                mc.MOV(addr_add(imm(base), imm(i*WORD)), eax)
         if self.debug_markers:
-            self.mc.MOV(eax, imm(pos))
-            self.mc.MOV(addr_add(imm(self.fail_box_int_addr),
+            mc.MOV(eax, imm(pos))
+            mc.MOV(addr_add(imm(self.fail_box_int_addr),
                                  imm(len(locs) * WORD)),
                                  eax)
         if exc:
-            self.generate_exception_handling(eax)
+            # note that we don't have to save and restore eax, ecx and edx here
+            addr = self.cpu.get_save_exception_int()
+            mc.CALL(rel32(addr))
         # don't break the following code sequence!
-        mc = self.mc._mc
-        self.places_to_patch_framesize.append(mc.tell())
-        mc.ADD(esp, imm32(0))
+        mc = mc._mc
+        mc.LEA(esp, addr_add(imm(0), ebp, (-RET_BP + 2) * WORD))
         guard_index = self.cpu.make_guard_index(op)
         mc.MOV(eax, imm(guard_index))
         mc.POP(edi)
@@ -731,19 +668,10 @@
         mc.POP(ebp)
         mc.RET()
 
-    def generate_exception_handling(self, loc):
-        self.mc.MOV(loc, heap(self._exception_addr))
-        self.mc.MOV(heap(self._exception_bck_addr), loc)
-        self.mc.MOV(loc, addr_add(imm(self._exception_addr), imm(WORD)))
-        self.mc.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)), loc)
-        # clean up the original exception, we don't want
-        # to enter more rpython code with exc set
-        self.mc.MOV(heap(self._exception_addr), imm(0))
-        self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0))
-
     @specialize.arg(3)
     def implement_guard(self, addr, guard_op, emit_jump):
         emit_jump(rel32(addr))
+        guard_op._x86_addr = self.mc.tell() - 4
 
     def genop_call(self, op, arglocs, resloc):
         sizeloc = arglocs[0]
@@ -808,15 +736,6 @@
         print "not implemented operation (guard): %s" % op.getopname()
         raise NotImplementedError
 
-    #def genop_call__1(self, op, arglocs, resloc):
-    #    self.gen_call(op, arglocs, resloc)
-    #    self.mc.MOVZX(eax, al)
-
-    #def genop_call__2(self, op, arglocs, resloc):
-    #    # XXX test it test it test it
-    #    self.gen_call(op, arglocs, resloc)
-    #    self.mc.MOVZX(eax, eax)
-
     def mark_gc_roots(self):
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py	Thu Sep 10 16:45:13 2009
@@ -18,6 +18,9 @@
 REGS = [eax, ecx, edx, ebx, esi, edi]
 WORD = 4
 
+class NoVariableToSpill(Exception):
+    pass
+
 class TempBox(Box):
     def __init__(self):
         pass
@@ -54,46 +57,56 @@
     exc = False
     
     def __init__(self, assembler, tree, translate_support_code=False,
-                 regalloc=None, guard_op=None):
+                 guard_op=None):
         # variables that have place in register
         self.assembler = assembler
         self.translate_support_code = translate_support_code
-        if regalloc is None:
-            cpu = self.assembler.cpu
+        cpu = self.assembler.cpu
+        self.reg_bindings = newcheckdict()
+        self.stack_bindings = newcheckdict()
+        self.tree = tree
+        if guard_op is not None:
+            locs = guard_op._x86_faillocs
+            cpu.gc_ll_descr.rewrite_assembler(cpu, guard_op.suboperations)
+            inpargs = [arg for arg in guard_op._fail_op.args if
+                       isinstance(arg, Box)]
+            self._compute_vars_longevity(inpargs, guard_op.suboperations)
+            self.inputargs = inpargs
+            self.position = -1
+            self._update_bindings(locs, inpargs)
+            self.current_stack_depth = guard_op._x86_current_stack_depth
+            self.loop_consts = {}
+        else:
             cpu.gc_ll_descr.rewrite_assembler(cpu, tree.operations)
-            self.tree = tree
-            self.reg_bindings = newcheckdict()
-            self.stack_bindings = newcheckdict()
-            # compute longevity of variables
             self._compute_vars_longevity(tree.inputargs, tree.operations)
-            self.free_regs = REGS[:]
+            # compute longevity of variables
             jump = tree.operations[-1]
             loop_consts = self._compute_loop_consts(tree.inputargs, jump)
             self.loop_consts = loop_consts
             self.current_stack_depth = 0
-        else:
-            inp = guard_op.inputargs
-            assert inp is not None
-            self.reg_bindings = {}
-            self.stack_bindings = {}
-            for arg in inp:
-                if arg in regalloc.reg_bindings:
-                    self.reg_bindings[arg] = regalloc.reg_bindings[arg]
-                if arg in regalloc.stack_bindings:
-                    self.stack_bindings[arg] = regalloc.stack_bindings[arg]
-                else:
-                    assert arg in regalloc.reg_bindings
-            allocated_regs = self.reg_bindings.values()
-            self.free_regs = [v for v in REGS if v not in allocated_regs]
-            self.current_stack_depth = regalloc.current_stack_depth
-            self.longevity = guard_op.longevity
-            jump_or_fail = guard_op.suboperations[-1]
-            self.loop_consts = {}
-            self.tree = regalloc.tree
+            self.free_regs = REGS[:]
 
-    def regalloc_for_guard(self, guard_op):
-        return RegAlloc(self.assembler, None, self.translate_support_code,
-                        self, guard_op)
+    def _update_bindings(self, locs, args):
+        newlocs = []
+        for loc in locs:
+            if not isinstance(loc, IMM8) and not isinstance(loc, IMM32):
+                newlocs.append(loc)
+        locs = newlocs
+        assert len(locs) == len(args)
+        used = {}
+        for i in range(len(locs)):
+            v = args[i]
+            loc = locs[i]
+            if isinstance(loc, REG) and self.longevity[v][1] > -1:
+                self.reg_bindings[v] = loc
+                used[loc] = None
+            else:
+                self.stack_bindings[v] = loc
+        self.free_regs = []
+        for reg in REGS:
+            if reg not in used:
+                self.free_regs.append(reg)
+        self._check_invariants()
 
     def _compute_loop_consts(self, inputargs, jump):
         if jump.opnum != rop.JUMP or jump.jump_target is not self.tree:
@@ -136,24 +149,22 @@
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
         self.assembler.regalloc_perform(op, arglocs, result_loc)
 
-    def perform_with_guard(self, op, guard_op, regalloc, arglocs, result_loc):
+    def perform_with_guard(self, op, guard_op, locs, arglocs, result_loc):
+        guard_op._x86_current_stack_depth = self.current_stack_depth
         if not we_are_translated():
             self.assembler.dump('%s <- %s(%s) [GUARDED]' % (result_loc, op,
                                                             arglocs))
-        self.assembler.regalloc_perform_with_guard(op, guard_op, regalloc,
+        self.assembler.regalloc_perform_with_guard(op, guard_op, locs,
                                                    arglocs, result_loc)
-        self.max_stack_depth = max(self.max_stack_depth,
-                                   regalloc.max_stack_depth)
 
-    def perform_guard(self, op, regalloc, arglocs, result_loc):
+    def perform_guard(self, op, locs, arglocs, result_loc):
+        op._x86_current_stack_depth = self.current_stack_depth
         if not we_are_translated():
             if result_loc is not None:
                 self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
             else:
                 self.assembler.dump('%s(%s)' % (op, arglocs))
-        self.assembler.regalloc_perform_guard(op, regalloc, arglocs, result_loc)
-        self.max_stack_depth = max(self.max_stack_depth,
-                                   regalloc.max_stack_depth)
+        self.assembler.regalloc_perform_guard(op, locs, arglocs, result_loc)
 
     def PerformDiscard(self, op, arglocs):
         if not we_are_translated():
@@ -170,25 +181,24 @@
         if operations[i + 1].args[0] is not op.result:
             return False
         if (self.longevity[op.result][1] > i + 1 or
-            op.result in operations[i + 1].inputargs):
-            print "!!!! boolean flag not optimized away !!!!"
+            op.result in operations[i + 1].suboperations[0].args):
             return False
         return True
 
     def walk_operations(self, tree):
         # first pass - walk along the operations in order to find
         # load/store places
-        operations = tree.operations
         self.position = -1
+        operations = tree.operations
         self.process_inputargs(tree)
         self._walk_operations(operations)
 
-    def walk_guard_ops(self, inputargs, operations, exc):
-        self.exc = exc
-        old_regalloc = self.assembler._regalloc
-        self.assembler._regalloc = self
-        self._walk_operations(operations)
-        self.assembler._regalloc = old_regalloc
+    #def walk_guard_ops(self, inputargs, operations, exc):
+    #    self.exc = exc
+    #    old_regalloc = self.assembler._regalloc
+    #    self.assembler._regalloc = self
+    #    self._walk_operations(operations)
+    #    self.assembler._regalloc = old_regalloc
 
     def _walk_operations(self, operations):
         i = 0
@@ -210,11 +220,8 @@
             i += 1
         assert not self.reg_bindings
         jmp = operations[-1]
-        #if jmp.opnum == rop.JUMP and jmp.jump_target is not self.tree:
-        #    self.max_stack_depth = max(jmp.jump_target._x86_stack_depth,
-        #                               self.max_stack_depth)
-        self.max_stack_depth = max(self.max_stack_depth,
-                                   self.current_stack_depth + 1)
+        self.max_stack_depth = max(self.current_stack_depth,
+                                   self.max_stack_depth)
 
     def _compute_vars_longevity(self, inputargs, operations):
         # compute a dictionary that maps variables to index in
@@ -234,8 +241,7 @@
                         raise AssertionError
                     longevity[arg] = (start_live[arg], i)
             if op.is_guard():
-                self._compute_inpargs(op)
-                for arg in op.inputargs:
+                for arg in op.suboperations[0].args:
                     if isinstance(arg, Box):
                         if arg not in start_live:
                             print "Bogus arg in guard %d at %d" % (op.opnum, i)
@@ -248,35 +254,32 @@
             assert isinstance(arg, Box)
         self.longevity = longevity
 
-    def _compute_inpargs(self, guard):
-        if guard.inputargs is not None:
-            return
-        operations = guard.suboperations
-        longevity = {}
-        end = {}
-        for i in range(len(operations)-1, -1, -1):
-            op = operations[i]
-            if op.is_guard():
-                self._compute_inpargs(op)
-                for arg in op.inputargs:
-                    if isinstance(arg, Box) and arg not in end:
-                        end[arg] = i
-            for arg in op.args:
-                if isinstance(arg, Box) and arg not in end:
-                    end[arg] = i
-            if op.result:
-                if op.result in end:
-                    longevity[op.result] = (i, end[op.result])
-                    del end[op.result]
-                # otherwise this var is never ever used
-        for v, e in end.items():
-            longevity[v] = (0, e)
-        guard.longevity = longevity
-        guard.inputargs = end.keys()
-        for arg in longevity:
-            assert isinstance(arg, Box)
-        for arg in guard.inputargs:
-            assert isinstance(arg, Box)
+#     def _compute_inpargs(self, guard):
+#         operations = guard.suboperations
+#         longevity = {}
+#         end = {}
+#         for i in range(len(operations)-1, -1, -1):
+#             op = operations[i]
+#             if op.is_guard():
+#                 for arg in op.suboperations[0].args:
+#                     if isinstance(arg, Box) and arg not in end:
+#                         end[arg] = i
+#             for arg in op.args:
+#                 if isinstance(arg, Box) and arg not in end:
+#                     end[arg] = i
+#             if op.result:
+#                 if op.result in end:
+#                     longevity[op.result] = (i, end[op.result])
+#                     del end[op.result]
+#                 # otherwise this var is never ever used
+#         for v, e in end.items():
+#             longevity[v] = (0, e)
+#         inputargs = end.keys()
+#         for arg in longevity:
+#             assert isinstance(arg, Box)
+#         for arg in inputargs:
+#             assert isinstance(arg, Box)
+#         return inputargs, longevity
 
     def try_allocate_reg(self, v, selected_reg=None, need_lower_byte=False):
         assert not isinstance(v, Const)
@@ -424,24 +427,30 @@
             reg = self.reg_bindings[next]
             if next in forbidden_vars:
                 continue
-            if selected_reg is not None and reg is selected_reg:
-                return next
+            if selected_reg is not None:
+                if reg is selected_reg:
+                    return next
+                else:
+                    continue
             if need_lower_byte and (reg is esi or reg is edi):
                 continue
-            candidates.append(next)
-        assert candidates
-        if len(candidates) == 1:
-            return candidates[0]
-        max = 0
-        chosen = None
-        for one in candidates:
-            next_usage = self._compute_next_usage(one, self.position)
-            if next_usage == -1:
-                return one
-            elif next_usage > max:
-                next_usage = max
-                chosen = one
-        return chosen
+            return next
+        raise NoVariableToSpill
+        # below is the slightly better (even optimal, under certain
+        # assumptions) algorithm, which is slow. Just go with the
+        # first hit
+        #if len(candidates) == 1:
+        #    return candidates[0]
+        #max = 0
+        #chosen = None
+        #for one in candidates:
+        #    next_usage = self._compute_next_usage(one, self.position)
+        #    if next_usage == -1:
+        #        return one
+        #    elif next_usage > max:
+        #        next_usage = max
+        #        chosen = one
+        #return chosen
 
     def move_variable_away(self, v, prev_loc):
         reg = None
@@ -482,6 +491,10 @@
             loc = self.reg_bindings[result_v]
         return loc
 
+    def locs_for_fail(self, guard_op):
+        assert len(guard_op.suboperations) == 1
+        return [self.loc(v) for v in guard_op.suboperations[0].args]
+
     def process_inputargs(self, tree):
         # XXX we can sort out here by longevity if we need something
         # more optimal
@@ -504,16 +517,17 @@
                 locs[i] = loc
             # otherwise we have it saved on stack, so no worry
         self.free_regs.insert(0, tmpreg)
+        assert tmpreg not in locs
         tree.arglocs = locs
         self.assembler.make_merge_point(tree, locs)
         self.eventually_free_vars(inputargs)
 
     def _consider_guard(self, op, ignored):
         loc = self.make_sure_var_in_reg(op.args[0], [])
-        regalloc = self.regalloc_for_guard(op)
-        self.perform_guard(op, regalloc, [loc], None)
+        locs = self.locs_for_fail(op)
+        self.perform_guard(op, locs, [loc], None)
         self.eventually_free_var(op.args[0])
-        self.eventually_free_vars(op.inputargs)
+        self.eventually_free_vars(op.suboperations[0].args)
 
     consider_guard_true = _consider_guard
     consider_guard_false = _consider_guard
@@ -521,13 +535,13 @@
     def consider_fail(self, op, ignored):
         # make sure all vars are on stack
         locs = [self.loc(arg) for arg in op.args]
-        self.assembler.generate_failure(op, locs, self.exc)
+        self.assembler.generate_failure(self.assembler.mc, op, locs, self.exc)
         self.eventually_free_vars(op.args)
 
     def consider_guard_no_exception(self, op, ignored):
-        regalloc = self.regalloc_for_guard(op)
-        self.perform_guard(op, regalloc, [], None)
-        self.eventually_free_vars(op.inputargs)
+        faillocs = self.locs_for_fail(op)
+        self.perform_guard(op, faillocs, [], None)
+        self.eventually_free_vars(op.suboperations[0].args)
 
     def consider_guard_exception(self, op, ignored):
         loc = self.make_sure_var_in_reg(op.args[0], [])
@@ -538,9 +552,9 @@
             resloc = self.force_allocate_reg(op.result, op.args + [box])
         else:
             resloc = None
-        regalloc = self.regalloc_for_guard(op)
-        self.perform_guard(op, regalloc, [loc, loc1], resloc)
-        self.eventually_free_vars(op.inputargs)
+        faillocs = self.locs_for_fail(op)
+        self.perform_guard(op, faillocs, [loc, loc1], resloc)
+        self.eventually_free_vars(op.suboperations[0].args)
         self.eventually_free_vars(op.args)
         self.eventually_free_var(box)
 
@@ -550,18 +564,18 @@
     def consider_guard_value(self, op, ignored):
         x = self.make_sure_var_in_reg(op.args[0], [])
         y = self.loc(op.args[1])
-        regalloc = self.regalloc_for_guard(op)
-        self.perform_guard(op, regalloc, [x, y], None)
-        self.eventually_free_vars(op.inputargs)
+        faillocs = self.locs_for_fail(op)
+        self.perform_guard(op, faillocs, [x, y], None)
+        self.eventually_free_vars(op.suboperations[0].args)
         self.eventually_free_vars(op.args)
 
     def consider_guard_class(self, op, ignored):
         assert isinstance(op.args[0], Box)
         x = self.make_sure_var_in_reg(op.args[0], [])
         y = self.loc(op.args[1])
-        regalloc = self.regalloc_for_guard(op)
-        self.perform_guard(op, regalloc, [x, y], None)
-        self.eventually_free_vars(op.inputargs)
+        faillocs = self.locs_for_fail(op)
+        self.perform_guard(op, faillocs, [x, y], None)
+        self.eventually_free_vars(op.suboperations[0].args)
         self.eventually_free_vars(op.args)
     
     def _consider_binop_part(self, op, ignored):
@@ -640,11 +654,11 @@
                                           need_lower_byte=True)
             self.Perform(op, arglocs, loc)
         else:
-            regalloc = self.regalloc_for_guard(guard_op)
+            faillocs = self.locs_for_fail(guard_op)
             self.position += 1
-            self.perform_with_guard(op, guard_op, regalloc, arglocs, None)
+            self.perform_with_guard(op, guard_op, faillocs, arglocs, None)
             self.eventually_free_var(op.result)
-            self.eventually_free_vars(guard_op.inputargs)
+            self.eventually_free_vars(guard_op.suboperations[0].args)
 
     consider_int_lt = _consider_compop
     consider_int_gt = _consider_compop
@@ -864,11 +878,11 @@
         if guard_op is not None:
             argloc = self.make_sure_var_in_reg(op.args[0], [])
             self.eventually_free_var(op.args[0])
-            regalloc = self.regalloc_for_guard(guard_op)
+            faillocs = self.locs_for_fail(guard_op)
             self.position += 1
-            self.perform_with_guard(op, guard_op, regalloc, [argloc], None)
+            self.perform_with_guard(op, guard_op, faillocs, [argloc], None)
             self.eventually_free_var(op.result)
-            self.eventually_free_vars(guard_op.inputargs)            
+            self.eventually_free_vars(guard_op.suboperations[0].args)
         else:
             argloc = self.loc(op.args[0])
             self.eventually_free_var(op.args[0])
@@ -885,7 +899,6 @@
         self.eventually_free_var(op.args[0])
         resloc = self.force_allocate_reg(op.result, [])
         self.Perform(op, [argloc], resloc)
-    consider_cast_int_to_ptr = consider_same_as
     consider_cast_ptr_to_int = consider_same_as
 
     def consider_strlen(self, op, ignored):
@@ -926,6 +939,7 @@
                                            dst_locations, tmploc)
         self.eventually_free_var(box)
         self.eventually_free_vars(op.args)
+        self.max_stack_depth = op.jump_target._x86_stack_depth    
         self.PerformDiscard(op, [])
 
     def consider_debug_merge_point(self, op, ignored):

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py	Thu Sep 10 16:45:13 2009
@@ -10,7 +10,7 @@
 
 history.TreeLoop._x86_compiled = 0
 history.TreeLoop._x86_bootstrap_code = 0
-
+history.TreeLoop._x86_stack_depth = 0
 
 class CPU386(AbstractLLCPU):
     debug = True
@@ -21,16 +21,6 @@
                  gcdescr=None):
         AbstractLLCPU.__init__(self, rtyper, stats, translate_support_code,
                                gcdescr)
-        if not translate_support_code:
-            self.current_interpreter = LLInterpreter(self.rtyper)
-
-            def _store_exception(lle):
-                tp_i = self.cast_ptr_to_int(lle.args[0])
-                v_i = self.cast_gcref_to_int(lle.args[1])
-                self.assembler._exception_data[0] = tp_i
-                self.assembler._exception_data[1] = v_i
-            
-            self.current_interpreter._store_exception = _store_exception
         TP = lltype.GcArray(llmemory.GCREF)
         self._bootstrap_cache = {}
         self._guard_list = []
@@ -45,34 +35,12 @@
     def setup_once(self):
         pass
 
-    def get_exception(self):
-        self.assembler.make_sure_mc_exists()
-        return self.assembler._exception_bck[0]
-
-    def get_exc_value(self):
-        self.assembler.make_sure_mc_exists()
-        return self.cast_int_to_gcref(self.assembler._exception_bck[1])
-
-    def clear_exception(self):
-        self.assembler.make_sure_mc_exists()
-        self.assembler._exception_bck[0] = 0
-        self.assembler._exception_bck[1] = 0
-
-    def compile_operations(self, tree, bridge=None):
-        old_loop = tree._x86_compiled
-        if old_loop:
-            olddepth = tree._x86_stack_depth
-            oldlocs = tree.arglocs
+    def compile_operations(self, tree, guard_op=None):
+        if guard_op is not None:
+            self.assembler.assemble_from_guard(tree, guard_op)
         else:
-            oldlocs = None
-            olddepth = 0
-        stack_depth = self.assembler.assemble(tree)
-        newlocs = tree.arglocs
-        if old_loop != 0:
-            self.assembler.patch_jump(old_loop, tree._x86_compiled,
-                                      oldlocs, newlocs, olddepth,
-                                      tree._x86_stack_depth)
-
+            self.assembler.assemble_loop(tree)
+        
     def get_bootstrap_code(self, loop):
         addr = loop._x86_bootstrap_code
         if not addr:
@@ -119,7 +87,7 @@
         prev_interpreter = None
         if not self.translate_support_code:
             prev_interpreter = LLInterpreter.current_interpreter
-            LLInterpreter.current_interpreter = self.current_interpreter
+            LLInterpreter.current_interpreter = self.debug_ll_interpreter
         res = 0
         try:
             self.caught_exception = None

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py	Thu Sep 10 16:45:13 2009
@@ -2,6 +2,7 @@
 """ Tests for register allocation for common constructs
 """
 
+import py
 from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\
      BoxPtr, ConstPtr, TreeLoop
 from pypy.jit.metainterp.resoperation import rop, ResOperation
@@ -14,20 +15,33 @@
 from pypy.rpython.lltypesystem import rclass, rstr
 from pypy.jit.backend.x86.ri386 import *
 
+
 class DummyTree(object):
     operations = [ResOperation(rop.FAIL, [], None)]
     inputargs = []
 
+class MockGcDescr(GcCache):
+    def get_funcptr_for_new(self):
+        return 123
+    get_funcptr_for_newarray = get_funcptr_for_new
+    get_funcptr_for_newstr = get_funcptr_for_new
+    get_funcptr_for_newunicode = get_funcptr_for_new
+ 
+    def rewrite_assembler(self, cpu, operations):
+        pass
+
 class MockAssembler(object):
     gcrefs = None
 
-    def __init__(self, cpu=None):
+    def __init__(self, cpu=None, gc_ll_descr=None):
         self.loads = []
         self.stores = []
         self.performs = []
         self.lea = []
         self.cpu = cpu or CPU(None, None)
-        self.cpu.gc_ll_descr = MockGcDescr(False)
+        if gc_ll_descr is None:
+            gc_ll_descr = MockGcDescr(False)
+        self.cpu.gc_ll_descr = gc_ll_descr
 
     def dump(self, *args):
         pass
@@ -47,55 +61,25 @@
     def load_effective_addr(self, *args):
         self.lea.append(args)
 
-class MockGcRootMap(object):
-    def get_basic_shape(self):
-        return ['shape']
-    def add_ebp_offset(self, shape, offset):
-        shape.append(offset)
-    def add_ebx(self, shape):
-        shape.append('ebx')
-    def add_esi(self, shape):
-        shape.append('esi')
-    def add_edi(self, shape):
-        shape.append('edi')
-    def compress_callshape(self, shape):
-        assert shape[0] == 'shape'
-        return ['compressed'] + shape[1:]
-
-class MockGcDescr(GcCache):
-    def get_funcptr_for_new(self):
-        return 123
-    get_funcptr_for_newarray = get_funcptr_for_new
-    get_funcptr_for_newstr = get_funcptr_for_new
-    get_funcptr_for_newunicode = get_funcptr_for_new
+def fill_regs(regalloc, cls=BoxInt):
+    allboxes = []
+    for reg in REGS:
+        box = cls()
+        allboxes.append(box)
+        regalloc.reg_bindings[box] = reg
+    regalloc.free_regs = []
+    return allboxes
     
-    moving_gc = True
-    gcrootmap = MockGcRootMap()
-
-    def initialize(self):
-        pass
-    def rewrite_assembler(self, cpu, operations):
-        pass
-
-
 class RegAllocForTests(RegAlloc):
     position = 0
     def _compute_next_usage(self, v, _):
         return -1
 
 class TestRegallocDirect(object):
-    def fill_regs(self, regalloc, cls=BoxInt):
-        allboxes = []
-        for reg in REGS:
-            box = cls()
-            allboxes.append(box)
-            regalloc.reg_bindings[box] = reg
-        regalloc.free_regs = []
-        return allboxes
-    
+
     def test_make_sure_var_in_reg(self):
         regalloc = RegAlloc(MockAssembler(), DummyTree())
-        boxes = self.fill_regs(regalloc)
+        boxes = fill_regs(regalloc)
         box = boxes[-1]
         oldloc = regalloc.loc(box)
         newloc = regalloc.make_sure_var_in_reg(box, [])
@@ -136,7 +120,7 @@
     def test_registers_around_call(self):
         cpu = CPU(None, None)
         regalloc = RegAlloc(MockAssembler(cpu), DummyTree())
-        boxes = self.fill_regs(regalloc)
+        boxes = fill_regs(regalloc)
         TP = lltype.FuncType([], lltype.Void)
         calldescr = cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
         regalloc._check_invariants()
@@ -149,31 +133,10 @@
         assert len(regalloc.assembler.stores) == 3
         regalloc._check_invariants()
 
-    def test_mark_gc_roots(self):
-        cpu = CPU(None, None)
-        regalloc = RegAlloc(MockAssembler(cpu), DummyTree())
-        cpu = regalloc.assembler.cpu
-        boxes = self.fill_regs(regalloc, cls=BoxPtr)
-        TP = lltype.FuncType([], lltype.Signed)
-        calldescr = cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
-        regalloc._check_invariants()
-        for box in boxes:
-            regalloc.longevity[box] = (0, 1)
-        box = boxes[0]
-        regalloc.position = 0
-        regalloc.consider_call(ResOperation(rop.CALL, [box], BoxInt(),
-                                            calldescr), None)
-        assert len(regalloc.assembler.stores) == 3
-        #
-        mark = regalloc.get_mark_gc_roots(cpu.gc_ll_descr.gcrootmap)
-        assert mark[0] == 'compressed'
-        expected = ['ebx', 'esi', 'edi', -16, -20, -24]
-        assert dict.fromkeys(mark[1:]) == dict.fromkeys(expected)
-
     def test_registers_around_newstr(self):
         cpu = CPU(None, None)
         regalloc = RegAllocForTests(MockAssembler(cpu), DummyTree())
-        boxes = self.fill_regs(regalloc)
+        boxes = fill_regs(regalloc)
         regalloc._check_invariants()
         for box in boxes:
             regalloc.longevity[box] = (0, 1)
@@ -247,9 +210,9 @@
         gcref = self.cpu.get_latest_value_ref(index)
         return lltype.cast_opaque_ptr(T, gcref)
 
-    def attach_bridge(self, ops, loop, guard_op):
+    def attach_bridge(self, ops, loop, guard_op, **kwds):
         assert guard_op.is_guard()
-        bridge = self.parse(ops)
+        bridge = self.parse(ops, **kwds)
         guard_op.suboperations = bridge.operations
         self.cpu.compile_operations(loop, guard_op)
         return bridge
@@ -268,34 +231,6 @@
         self.interpret(ops, [0])
         assert self.getint(0) == 20
 
-    def test_compile_and_recompile(self):
-        ops = '''
-        [i0]
-        i1 = int_add(i0, 1)
-        i2 = int_lt(i1, 20)
-        guard_true(i2)
-           fail(i1)
-        jump(i1)
-        '''
-        loop = self.interpret(ops, [0])
-        assert self.getint(0) == 20
-        ops = '''
-        [i1]
-        i3 = int_add(i1, 1)
-        i4 = int_add(i3, 1)
-        i5 = int_add(i4, 1)
-        i6 = int_add(i5, 1)
-        fail(i3, i4, i5, i6)
-        '''
-        bridge = self.attach_bridge(ops, loop, loop.operations[-2])
-        self.cpu.set_future_value_int(0, 0)
-        op = self.cpu.execute_operations(loop)
-        assert op is bridge.operations[-1]
-        assert self.getint(0) == 21
-        assert self.getint(1) == 22
-        assert self.getint(2) == 23
-        assert self.getint(3) == 24
-
     def test_two_loops_and_a_bridge(self):
         ops = '''
         [i0, i1, i2, i3]
@@ -305,7 +240,7 @@
            fail(i4, i1, i2, i3)
         jump(i4, i1, i2, i3)
         '''
-        loop = self.interpret(ops, [0])
+        loop = self.interpret(ops, [0, 0, 0, 0])
         ops2 = '''
         [i5]
         i1 = int_add(i5, 1)
@@ -313,10 +248,18 @@
         i4 = int_add(i3, 1)
         i2 = int_lt(i4, 30)
         guard_true(i2)
-           jump(i4, i4, i4, i4)
+           fail(i4)
         jump(i4)
         '''
-        loop2 = self.interpret(ops2, [0], jump_targets=[loop, 'self'])
+        loop2 = self.interpret(ops2, [0])
+        bridge_ops = '''
+        [i4]
+        jump(i4, i4, i4, i4)
+        '''
+        bridge = self.attach_bridge(bridge_ops, loop2, loop2.operations[4],
+                                    jump_targets=[loop])
+        self.cpu.set_future_value_int(0, 0)
+        self.cpu.execute_operations(loop2)
         assert self.getint(0) == 31
         assert self.getint(1) == 30
         assert self.getint(2) == 30
@@ -339,18 +282,24 @@
         assert not self.cpu.assembler.fail_boxes_ptr[1]
 
     def test_exception_bridge_no_exception(self):
-
-        
         ops = '''
         [i0]
         call(ConstClass(raising_fptr), i0, descr=raising_calldescr)
         guard_exception(ConstClass(zero_division_error))
-            guard_no_exception()
-                fail(2)
             fail(1)
         fail(0)
         '''
-        self.interpret(ops, [0])
+        bridge_ops = '''
+        []
+        guard_no_exception()
+            fail(2)
+        fail(1)
+        '''
+        loop = self.interpret(ops, [0])
+        assert self.getint(0) == 1
+        bridge = self.attach_bridge(bridge_ops, loop, loop.operations[1])
+        self.cpu.set_future_value_int(0, 0)
+        self.cpu.execute_operations(loop)
         assert self.getint(0) == 1
 
     def test_inputarg_unused(self):
@@ -365,15 +314,43 @@
         ops = '''
         [i0, i1]
         guard_true(i0)
-            guard_true(i0)
-                fail(i0, i1)
-            fail(3)
+            fail(i0, i1)
         fail(4)
         '''
-        self.interpret(ops, [0, 10])
+        bridge_ops = '''
+        [i0, i1]
+        guard_true(i0)
+            fail(i0, i1)
+        fail(3)
+        '''
+        loop = self.interpret(ops, [0, 10])
+        assert self.getint(0) == 0
+        assert self.getint(1) == 10
+        bridge = self.attach_bridge(bridge_ops, loop, loop.operations[0])
+        self.cpu.set_future_value_int(0, 0)
+        self.cpu.set_future_value_int(1, 10)
+        self.cpu.execute_operations(loop)
         assert self.getint(0) == 0
         assert self.getint(1) == 10
 
+    def test_nested_unused_arg(self):
+        ops = '''
+        [i0, i1]
+        guard_true(i0)
+           fail(i0, i1)
+        fail(1)
+        '''
+        loop = self.interpret(ops, [0, 1])
+        assert self.getint(0) == 0
+        bridge_ops = '''
+        [i0, i1]
+        fail(1, 2)
+        '''
+        self.attach_bridge(bridge_ops, loop, loop.operations[0])
+        self.cpu.set_future_value_int(0, 0)
+        self.cpu.set_future_value_int(1, 1)
+        self.cpu.execute_operations(loop)
+
     def test_spill_for_constant(self):
         ops = '''
         [i0, i1, i2, i3]
@@ -476,6 +453,26 @@
         self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0])
         assert self.getint(0) == 0
 
+    def test_bug_wrong_stack_adj(self):
+        ops = '''
+        [i0, i1, i2, i3, i4, i5, i6, i7, i8]
+        guard_true(i0)
+            fail(0, i0, i1, i2, i3, i4, i5, i6, i7, i8)
+        fail(1, i0, i1, i2, i3, i4, i5, i6, i7, i8)
+        '''
+        loop = self.interpret(ops, [0, 1, 2, 3, 4, 5, 6, 7, 8])
+        assert self.getint(0) == 0
+        bridge_ops = '''
+        [i0, i1, i2, i3, i4, i5, i6, i7, i8]
+        call(ConstClass(raising_fptr), 0, descr=raising_calldescr)
+        fail(i0, i1, i2, i3, i4, i5, i6, i7, i8)
+        '''
+        self.attach_bridge(bridge_ops, loop, loop.operations[0])
+        for i in range(9):
+            self.cpu.set_future_value_int(i, i)
+        self.cpu.execute_operations(loop)
+        assert self.getints(9) == range(9)
+
 class TestRegallocCompOps(BaseTestRegalloc):
     
     def test_cmp_op_0(self):
@@ -574,99 +571,3 @@
         s = lltype.malloc(self.A, 3)
         self.interpret(ops, [s, ord('a')])
         assert s[1] == 'a'
-        
-
-class TestRegallocGc(BaseTestRegalloc):
-    cpu = CPU(None, None)
-    cpu.gc_ll_descr = MockGcDescr(False)
-    
-    S = lltype.GcForwardReference()
-    S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)),
-                             ('int', lltype.Signed)))
-
-    fielddescr = cpu.fielddescrof(S, 'field')
-
-    struct_ptr = lltype.malloc(S)
-    struct_ref = lltype.cast_opaque_ptr(llmemory.GCREF, struct_ptr)
-    child_ptr = lltype.nullptr(S)
-    struct_ptr.field = child_ptr
-
-
-    descr0 = cpu.fielddescrof(S, 'int')
-    ptr0 = struct_ref
-
-    namespace = locals().copy()
-
-    def test_basic(self):
-        ops = '''
-        [p0]
-        p1 = getfield_gc(p0, descr=fielddescr)
-        fail(p1)
-        '''
-        self.interpret(ops, [self.struct_ptr])
-        assert not self.getptr(0, lltype.Ptr(self.S))
-
-    def test_rewrite_constptr(self):
-        ops = '''
-        []
-        p1 = getfield_gc(ConstPtr(struct_ref), descr=fielddescr)
-        fail(p1)
-        '''
-        self.interpret(ops, [])
-        assert not self.getptr(0, lltype.Ptr(self.S))
-        
-    def test_rewrite_constptr_in_brdige(self):
-        ops = '''
-        [i0]
-        guard_true(i0)
-            p1 = getfield_gc(ConstPtr(struct_ref), descr=fielddescr)
-            fail(p1)
-        fail(0)
-        '''
-        self.interpret(ops, [0])
-        assert not self.getptr(0, lltype.Ptr(self.S))
-
-    def test_bug_0(self):
-        ops = '''
-        [i0, i1, i2, i3, i4, i5, i6, i7, i8]
-        guard_value(i2, 1)
-            fail(i2, i3, i4, i5, i6, i7, i0, i1, i8)
-        guard_class(i4, 138998336)
-            fail(i4, i5, i6, i7, i0, i1, i8)
-        i11 = getfield_gc(i4, descr=descr0)
-        i12 = ooisnull(i11)
-        guard_false(i12)
-            fail(i4, i5, i6, i7, i0, i1, i11, i8)
-        i13 = getfield_gc(i11, descr=descr0)
-        i14 = ooisnull(i13)
-        guard_true(i14)
-            fail(i4, i5, i6, i7, i0, i1, i11, i8)
-        i15 = getfield_gc(i4, descr=descr0)
-        i17 = int_lt(i15, 0)
-        guard_false(i17)
-            fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
-        i18 = getfield_gc(i11, descr=descr0)
-        i19 = int_ge(i15, i18)
-        guard_false(i19)
-            fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
-        i20 = int_lt(i15, 0)
-        guard_false(i20)
-            fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
-        i21 = getfield_gc(i11, descr=descr0)
-        i22 = getfield_gc(i11, descr=descr0)
-        i23 = int_mul(i15, i22)
-        i24 = int_add(i21, i23)
-        i25 = getfield_gc(i4, descr=descr0)
-        i27 = int_add(i25, 1)
-        setfield_gc(i4, i27, descr=descr0)
-        i29 = getfield_raw(144839744, descr=descr0)
-        i31 = int_and(i29, -2141192192)
-        i32 = int_is_true(i31)
-        guard_false(i32)
-            fail(i4, i6, i7, i0, i1, i24)
-        i33 = getfield_gc(i0, descr=descr0)
-        guard_value(i33, ConstPtr(ptr0))
-            fail(i4, i6, i7, i0, i1, i33, i24)
-        jump(i0, i1, 1, 17, i4, ConstPtr(ptr0), i6, i7, i24)
-        '''
-        self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0, 0], run=False)

Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py	Thu Sep 10 16:45:13 2009
@@ -8,6 +8,7 @@
     # for the individual tests see
     # ====> ../../../metainterp/test/test_virtual.py
     _new_op = 'new_with_vtable'
+    _field_prefix = 'inst_'
     
     @staticmethod
     def _new():

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py	Thu Sep 10 16:45:13 2009
@@ -251,7 +251,8 @@
         graph, oosend_methdescr = graph_key
         self.bytecode = self.codewriter.get_jitcode(graph,
                                              oosend_methdescr=oosend_methdescr)
-        if not codewriter.policy.look_inside_graph(graph):
+        if not codewriter.policy.look_inside_graph(graph,
+                                                   self.cpu.supports_floats):
             assert not portal, "portal has been hidden!"
             graph = make_calling_stub(codewriter.rtyper, graph)
         self.graph = graph
@@ -612,6 +613,9 @@
     def serialize_op_uint_xor(self, op): self._defl(op, 'int_xor')
     def serialize_op_uint_lshift(self, op): self._defl(op, 'int_lshift')
 
+    def serialize_op_cast_bool_to_float(self, op):
+        self.default_serialize_op(op, 'cast_int_to_float')
+
     serialize_op_unichar_eq = serialize_op_char_eq
     serialize_op_unichar_ne = serialize_op_char_ne
 
@@ -717,7 +721,8 @@
                 pass
             else:
                 if hasattr(rtti._obj, 'destructor_funcptr'):
-                    self.handle_builtin_call(op)
+                    c_vtable = Constant(vtable, lltype.typeOf(vtable))
+                    self._do_builtin_call(op, 'alloc_with_del', [c_vtable])
                     return
             # store the vtable as an address -- that's fine, because the
             # GC doesn't need to follow them
@@ -751,6 +756,21 @@
                   self.const_position(cls))
         self.codewriter.register_known_ooclass(cls, TYPE)
         self.register_var(op.result)
+        # initialize fields with a non-default value: while in ootype it's
+        # new() that takes care of it, for the jit we explicitly insert the
+        # corresponding setfields(). This way, the backends don't need to care
+        # about default fields and moreover the resulting code is more similar
+        # to the lltype version, so the optimizer doesn't need to take special
+        # care for them.
+        if isinstance(TYPE, ootype.Instance):
+            fields = TYPE._get_fields_with_different_default()
+            var_inst = self.var_position(op.result)
+            for name, (T, value) in fields:
+                descr = self.cpu.fielddescrof(TYPE, name)
+                self.emit('setfield_gc')
+                self.emit(var_inst)
+                self.emit(self.get_position(descr))
+                self.emit(self.var_position(Constant(value)))
 
     def serialize_op_oonewarray(self, op):
         ARRAY = op.args[0].value
@@ -1003,20 +1023,24 @@
             self.emit('can_enter_jit')
 
     def serialize_op_direct_call(self, op):
-        kind = self.codewriter.policy.guess_call_kind(op)
+        kind = self.codewriter.policy.guess_call_kind(op,
+                                           self.codewriter.cpu.supports_floats)
         return getattr(self, 'handle_%s_call' % kind)(op)
 
     def serialize_op_indirect_call(self, op):
-        kind = self.codewriter.policy.guess_call_kind(op)
+        kind = self.codewriter.policy.guess_call_kind(op,
+                                           self.codewriter.cpu.supports_floats)
         return getattr(self, 'handle_%s_indirect_call' % kind)(op)
 
     def serialize_op_oosend(self, op):
-        kind = self.codewriter.policy.guess_call_kind(op)
+        kind = self.codewriter.policy.guess_call_kind(op,
+                                           self.codewriter.cpu.supports_floats)
         return getattr(self, 'handle_%s_oosend' % kind)(op)
 
     def handle_regular_call(self, op, oosend_methdescr=None):
         self.minimize_variables()
-        [targetgraph] = self.codewriter.policy.graphs_from(op)
+        [targetgraph] = self.codewriter.policy.graphs_from(op,
+                                           self.codewriter.cpu.supports_floats)
         jitbox = self.codewriter.get_jitcode(targetgraph, self.graph,
                                              oosend_methdescr=oosend_methdescr)
         if oosend_methdescr:
@@ -1063,6 +1087,8 @@
         calldescr, non_void_args = self.codewriter.getcalldescr(op.args[0],
                                                                 args,
                                                                 op.result)
+        self.emit('recursion_leave_prep')
+        self.emit_varargs(non_void_args)        
         self.emit('recursive_call')
         self.emit(self.get_position(calldescr))
         self.emit_varargs([op.args[0]] + non_void_args)
@@ -1071,7 +1097,8 @@
     handle_residual_indirect_call = handle_residual_call
 
     def handle_regular_indirect_call(self, op):
-        targets = self.codewriter.policy.graphs_from(op)
+        targets = self.codewriter.policy.graphs_from(op,
+                                           self.codewriter.cpu.supports_floats)
         assert targets is not None
         self.minimize_variables()
         indirectcallset = self.codewriter.get_indirectcallset(targets)
@@ -1101,6 +1128,9 @@
 
     def handle_builtin_call(self, op):
         oopspec_name, args = support.decode_builtin_call(op)
+        return self._do_builtin_call(op, oopspec_name, args)
+
+    def _do_builtin_call(self, op, oopspec_name, args):
         argtypes = [v.concretetype for v in args]
         resulttype = op.result.concretetype
         c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper,

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py	Thu Sep 10 16:45:13 2009
@@ -7,7 +7,7 @@
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.history import TreeLoop, log, Box, History
 from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj,\
-     Const
+     BoxFloat, Const
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.specnode import NotSpecNode
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
@@ -163,6 +163,17 @@
             result = resultbox.getref_base()
         raise metainterp_sd.DoneWithThisFrameRef(cpu, result)
 
+class DoneWithThisFrameDescrFloat(AbstractDescr):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == 'float'
+        resultbox = fail_op.args[0]
+        if isinstance(resultbox, BoxFloat):
+            result = metainterp_sd.cpu.get_latest_value_float(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getfloat()
+        raise metainterp_sd.DoneWithThisFrameFloat(result)
+
 class ExitFrameWithExceptionDescrRef(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
         assert len(fail_op.args) == 1
@@ -178,6 +189,7 @@
 done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
 done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
 done_with_this_frame_descr_ref = DoneWithThisFrameDescrRef()
+done_with_this_frame_descr_float = DoneWithThisFrameDescrFloat()
 exit_frame_with_exception_descr_ref = ExitFrameWithExceptionDescrRef()
 
 class TerminatingLoop(TreeLoop):
@@ -204,6 +216,12 @@
 _loop.finishdescr = done_with_this_frame_descr_ref
 oohelper.loops_done_with_this_frame_ref = [_loop]
 
+_loop = TerminatingLoop('done_with_this_frame_float')
+_loop.specnodes = [prebuiltNotSpecNode]
+_loop.inputargs = [BoxFloat()]
+_loop.finishdescr = done_with_this_frame_descr_float
+loops_done_with_this_frame_float = [_loop]
+
 _loop = TerminatingLoop('done_with_this_frame_void')
 _loop.specnodes = []
 _loop.inputargs = []

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py	Thu Sep 10 16:45:13 2009
@@ -7,7 +7,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask
 from pypy.jit.metainterp.history import BoxInt, ConstInt, check_descr
-from pypy.jit.metainterp.history import INT, REF
+from pypy.jit.metainterp.history import INT, REF, ConstFloat
 from pypy.jit.metainterp.resoperation import rop
 
 
@@ -218,6 +218,53 @@
     cpu._overflow_flag = ovf
     return BoxInt(z)
 
+# ----------
+
+def do_float_neg(cpu, args, descr=None):
+    return ConstFloat(-args[0].getfloat())
+
+def do_float_abs(cpu, args, descr=None):
+    return ConstFloat(abs(args[0].getfloat()))
+
+def do_float_is_true(cpu, args, descr=None):
+    return ConstInt(bool(args[0].getfloat()))
+
+def do_float_add(cpu, args, descr=None):
+    return ConstFloat(args[0].getfloat() + args[1].getfloat())
+
+def do_float_sub(cpu, args, descr=None):
+    return ConstFloat(args[0].getfloat() - args[1].getfloat())
+
+def do_float_mul(cpu, args, descr=None):
+    return ConstFloat(args[0].getfloat() * args[1].getfloat())
+
+def do_float_truediv(cpu, args, descr=None):
+    return ConstFloat(args[0].getfloat() / args[1].getfloat())
+
+def do_float_lt(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() < args[1].getfloat())
+
+def do_float_le(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() <= args[1].getfloat())
+
+def do_float_eq(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() == args[1].getfloat())
+
+def do_float_ne(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() != args[1].getfloat())
+
+def do_float_gt(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() > args[1].getfloat())
+
+def do_float_ge(cpu, args, descr=None):
+    return ConstInt(args[0].getfloat() >= args[1].getfloat())
+
+def do_cast_float_to_int(cpu, args, descr=None):
+    return ConstInt(int(args[0].getfloat()))
+
+def do_cast_int_to_float(cpu, args, descr=None):
+    return ConstFloat(float(args[0].getint()))
+
 # ____________________________________________________________
 
 def do_debug_merge_point(cpu, args, descr=None):

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py	Thu Sep 10 16:45:13 2009
@@ -16,13 +16,16 @@
 
 # ____________________________________________________________
 
-INT = 'i'
-REF = 'r'
+INT   = 'i'
+REF   = 'r'
+FLOAT = 'f'
 
-def getkind(TYPE):
+def getkind(TYPE, supports_floats=True):
     if TYPE is lltype.Void:
         return "void"
     elif isinstance(TYPE, lltype.Primitive):
+        if TYPE is lltype.Float and supports_floats:
+            return 'float'
         if TYPE in (lltype.Float, lltype.SingleFloat):
             raise NotImplementedError("type %s not supported" % TYPE)
         # XXX fix this for oo...
@@ -68,7 +71,7 @@
         self.seen = {}
     def repr_rpython(self, box, typechars):
         n = self.seen.setdefault(box, len(self.seen))
-        return '%s/%s%d' % (box.get_(), typechars, n)
+        return '%s/%s%d' % (box._get_hash_(), typechars, n)
 
 repr_rpython = ReprRPython().repr_rpython
 
@@ -79,6 +82,9 @@
     def getint(self):
         raise NotImplementedError
 
+    def getfloat(self):
+        raise NotImplementedError
+
     def getref_base(self):
         raise NotImplementedError
 
@@ -86,7 +92,7 @@
         raise NotImplementedError
     getref._annspecialcase_ = 'specialize:arg(1)'
 
-    def get_(self):
+    def _get_hash_(self):
         raise NotImplementedError
 
     def nonnull(self):
@@ -157,6 +163,8 @@
             return ConstInt(intval)
         elif kind == "ref":
             return cpu.ts.new_ConstRef(x)
+        elif kind == "float":
+            return ConstFloat(x)
         else:
             raise NotImplementedError(kind)
 
@@ -212,7 +220,7 @@
     def getaddr(self, cpu):
         return cpu.cast_int_to_adr(self.value)
 
-    def get_(self):
+    def _get_hash_(self):
         return self.value
 
     def nonnull(self):
@@ -258,7 +266,7 @@
     def getaddr(self, cpu):
         return self.value
 
-    def get_(self):
+    def _get_hash_(self):
         return llmemory.cast_adr_to_int(self.value)
 
     def nonnull(self):
@@ -276,6 +284,38 @@
     def repr_rpython(self):
         return repr_rpython(self, 'ca')
 
+class ConstFloat(Const):
+    type = FLOAT
+    value = 0.0
+    _attrs_ = ('value',)
+
+    def __init__(self, floatval):
+        assert isinstance(floatval, float)
+        self.value = floatval
+
+    def clonebox(self):
+        return BoxFloat(self.value)
+
+    nonconstbox = clonebox
+
+    def getfloat(self):
+        return self.value
+
+    def _get_hash_(self):
+        return hash(self.value)
+
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_float(j, self.getfloat())
+
+    def equals(self, other):
+        return self.value == other.getfloat()
+
+    def _getrepr_(self):
+        return self.value
+
+    def repr_rpython(self):
+        return repr_rpython(self, 'cf')
+
 class ConstPtr(Const):
     type = REF
     value = lltype.nullptr(llmemory.GCREF.TO)
@@ -297,7 +337,7 @@
         return lltype.cast_opaque_ptr(PTR, self.getref_base())
     getref._annspecialcase_ = 'specialize:arg(1)'
 
-    def get_(self):
+    def _get_hash_(self):
         return lltype.cast_ptr_to_int(self.value)
 
     def getaddr(self, cpu):
@@ -343,9 +383,9 @@
         return ootype.cast_from_object(OBJ, self.getref_base())
     getref._annspecialcase_ = 'specialize:arg(1)'
 
-    def get_(self):
+    def _get_hash_(self):
         if self.value:
-            return ootype.ooidentityhash(self.value) # XXX: check me
+            return ootype.ooidentityhash(self.value)
         else:
             return 0
 
@@ -390,6 +430,8 @@
             # XXX add ootype support?
             ptrval = lltype.cast_opaque_ptr(llmemory.GCREF, x)
             return BoxPtr(ptrval)
+        elif kind == "float":
+            return BoxFloat(x)
         else:
             raise NotImplementedError(kind)
 
@@ -448,7 +490,7 @@
     def getaddr(self, cpu):
         return cpu.cast_int_to_adr(self.value)
 
-    def get_(self):
+    def _get_hash_(self):
         return self.value
 
     def nonnull(self):
@@ -468,6 +510,40 @@
 
     changevalue_int = __init__
 
+class BoxFloat(Box):
+    type = FLOAT
+    _attrs_ = ('value',)
+    
+    def __init__(self, floatval=0.0):
+        assert isinstance(floatval, float)
+        self.value = floatval
+
+    def clonebox(self):
+        return BoxFloat(self.value)
+
+    def constbox(self):
+        return ConstFloat(self.value)
+
+    def getfloat(self):
+        return self.value
+
+    def _get_hash_(self):
+        return hash(self.value)
+
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_float(j, self.value)
+
+    def _getrepr_(self):
+        return self.value
+
+    def repr_rpython(self):
+        return repr_rpython(self, 'bf')
+
+    def changevalue_box(self, srcbox):
+        self.changevalue_float(srcbox.getfloat())
+
+    changevalue_float = __init__
+
 class BoxPtr(Box):
     type = REF
     _attrs_ = ('value',)
@@ -492,7 +568,7 @@
     def getaddr(self, cpu):
         return llmemory.cast_ptr_to_adr(self.value)
 
-    def get_(self):
+    def _get_hash_(self):
         return lltype.cast_ptr_to_int(self.value)
 
     def nonnull(self):
@@ -534,9 +610,9 @@
         return ootype.cast_from_object(OBJ, self.getref_base())
     getref._annspecialcase_ = 'specialize:arg(1)'
 
-    def get_(self):
+    def _get_hash_(self):
         if self.value:
-            return ootype.ooidentityhash(self.value) # XXX: check me
+            return ootype.ooidentityhash(self.value)
         else:
             return 0
 
@@ -577,7 +653,7 @@
     if isinstance(c.value, Symbolic):
         return id(c.value)
     try:
-        return c.get_()
+        return c._get_hash_()
     except lltype.DelayedPointer:
         return -2      # xxx risk of changing hash...
 
@@ -712,6 +788,7 @@
 
     compiled_count = 0
     enter_count = 0
+    aborted_count = 0
 
     def __init__(self):
         self.loops = []
@@ -777,10 +854,9 @@
 
 class Options:
     logger_noopt = None
-    def __init__(self, specialize=True, listops=False, inline=False):
+    def __init__(self, specialize=True, listops=False):
         self.specialize = specialize
         self.listops = listops
-        self.inline = inline
     def _freeze_(self):
         return True
 

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py	Thu Sep 10 16:45:13 2009
@@ -3,6 +3,7 @@
 """
 
 import time
+from pypy.rlib.debug import debug_print
 
 TRACING = 0
 BACKEND = 1
@@ -69,11 +70,11 @@
         t0 = self.t1
         self.t1 = self.timer()
         if not self.current:
-            print "BROKEN PROFILER DATA!"
+            debug_print("BROKEN PROFILER DATA!")
             return
         ev1 = self.current.pop()
         if ev1 != event:
-            print "BROKEN PROFILER DATA!"
+            debug_print("BROKEN PROFILER DATA!")
             return
         self.times[ev1] += self.t1 - t0
 

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py	Thu Sep 10 16:45:13 2009
@@ -560,7 +560,8 @@
 
     def optimize_GUARD_VALUE(self, op):
         assert isinstance(op.args[1], Const)
-        assert op.args[0].get_() == op.args[1].get_()
+        if not we_are_translated():
+            assert op.args[0].value == op.args[1].value
         self.optimize_guard(op)
 
     def optimize_GUARD_TRUE(self, op):

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py	Thu Sep 10 16:45:13 2009
@@ -16,20 +16,22 @@
             return False
         return True
 
-    def look_inside_graph(self, graph):
-        if contains_unsupported_variable_type(graph):
-            return False
+    def look_inside_graph(self, graph, supports_floats):
         try:
             func = graph.func
         except AttributeError:
-            return True
-        return self.look_inside_function(func)
+            see_function = True
+        else:
+            see_function = self.look_inside_function(func)
+        return (see_function and
+                not contains_unsupported_variable_type(graph,
+                                                       supports_floats))
 
-    def graphs_from(self, op):
+    def graphs_from(self, op, supports_floats):
         if op.opname == 'direct_call':
             funcobj = get_funcobj(op.args[0].value)
             graph = funcobj.graph
-            if self.look_inside_graph(graph):
+            if self.look_inside_graph(graph, supports_floats):
                 return [graph]     # common case: look inside this graph
         else:
             assert op.opname in ('indirect_call', 'oosend')
@@ -40,13 +42,13 @@
                 graphs = v_obj._lookup_graphs(op.args[0].value)
             if graphs is not None:
                 for graph in graphs:
-                    if self.look_inside_graph(graph):
+                    if self.look_inside_graph(graph, supports_floats):
                         return graphs  # common case: look inside at
                                        # least one of the graphs
         # residual call case: we don't need to look into any graph
         return None
 
-    def guess_call_kind(self, op):
+    def guess_call_kind(self, op, supports_floats):
         if op.opname == 'direct_call':
             funcobj = get_funcobj(op.args[0].value)
             if isinstance(lltype.typeOf(funcobj), lltype.Ptr):
@@ -69,20 +71,20 @@
                 return 'builtin'
             # TODO: return 'recursive' if the oosend ends with calling the
             # portal
-        if self.graphs_from(op) is None:
+        if self.graphs_from(op, supports_floats) is None:
             return 'residual'
         return 'regular'
 
-def contains_unsupported_variable_type(graph):
+def contains_unsupported_variable_type(graph, supports_floats):
     getkind = history.getkind
     try:
         for block in graph.iterblocks():
             for v in block.inputargs:
-                getkind(v.concretetype)
+                getkind(v.concretetype, supports_floats)
             for op in block.operations:
                 for v in op.args:
-                    getkind(v.concretetype)
-                getkind(op.result.concretetype)
+                    getkind(v.concretetype, supports_floats)
+                getkind(op.result.concretetype, supports_floats)
     except NotImplementedError, e:
         history.log.WARNING('%s, ignoring graph' % (e,))
         history.log.WARNING('  %s' % (graph,))
@@ -99,96 +101,3 @@
         if func in self.funcs:
             return False
         return super(StopAtXPolicy, self).look_inside_function(func)
-
-# ____________________________________________________________
-
-from pypy.annotation.specialize import getuniquenondirectgraph
-
-class ManualJitPolicy(JitPolicy):
-    def __init__(self, translator):
-        self.translator = translator
-        self.bookkeeper = translator.annotator.bookkeeper
-        self.enabled_graphs = {}
-        self.memo = {}
-        self.fill_seen_graphs()
-
-    def look_inside_graph(self, graph):
-        if graph in self.enabled_graphs:
-            return self.enabled_graphs[graph]
-        res = super(ManualJitPolicy, self).look_inside_graph(graph)
-        self.enabled_graphs[graph] = res     # cache the result
-        return res
-
-    def fill_seen_graphs(self):
-        # subclasses should have their own
-        pass
-
-    def _graph(self, func):
-        func = getattr(func, 'im_func', func)
-        desc = self.bookkeeper.getdesc(func)
-        return getuniquenondirectgraph(desc)
-
-    def seefunc(self, fromfunc, *tofuncs):
-        targetgraphs = {}
-        for tofunc in tofuncs:
-            targetgraphs[self._graph(tofunc)] = True
-        graphs = graphs_on_the_path_to(self.translator, self._graph(fromfunc),
-                                       targetgraphs, self.memo)
-        for graph in graphs:
-            if graph not in self.enabled_graphs:
-                self.enabled_graphs[graph] = True
-                print '++', graph
-
-    def seepath(self, *path):
-        assert len(path) >= 2
-        for i in range(1, len(path)):
-            self.seefunc(path[i-1], path[i])
-
-    def seegraph(self, func, look=True):
-        graph = self._graph(func)
-        self.enabled_graphs[graph] = look
-        if look:
-            print '++', graph
-        else:
-            print '--', graph
-
-def enumerate_reachable_graphs(translator, startgraph, memo=None):
-    from pypy.translator.backendopt.support import find_calls_from
-    pending = [(startgraph, None)]
-    yield pending[0]
-    seen = {startgraph: True}
-    while pending:
-        yield None     # hack: a separator meaning "length increases now"
-        nextlengthlist = []
-        nextseen = {}
-        for node in pending:
-            head, tail = node
-            for block, callee in find_calls_from(translator, head, memo):
-                if callee not in seen:
-                    newnode = callee, node
-                    yield newnode
-                    nextlengthlist.append(newnode)
-                    nextseen[callee] = True
-        pending = nextlengthlist
-        seen.update(nextseen)
-    yield None
-
-def graphs_on_the_path_to(translator, startgraph, targetgraphs, memo=None):
-    targetgraphs = targetgraphs.copy()
-    result = {}
-    found = {}
-    for node in enumerate_reachable_graphs(translator, startgraph, memo):
-        if node is None:  # hack: a separator meaning "length increases now"
-            for graph in found:
-                del targetgraphs[graph]
-            found.clear()
-            if not targetgraphs:
-                return result
-        elif node[0] in targetgraphs:
-            found[node[0]] = True
-            while node is not None:
-                head, tail = node
-                result[head] = True
-                node = tail
-    raise Exception("did not reach all targets:\nmissing %r" % (
-        targetgraphs.keys(),))

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py	Thu Sep 10 16:45:13 2009
@@ -227,6 +227,9 @@
                     'int_and', 'int_or', 'int_xor',
                     'int_rshift', 'int_lshift', 'uint_rshift',
                     'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
+                    'float_add', 'float_sub', 'float_mul', 'float_truediv',
+                    'float_lt', 'float_le', 'float_eq',
+                    'float_ne', 'float_gt', 'float_ge',
                     ]:
         exec py.code.Source('''
             @arguments("box", "box")
@@ -243,7 +246,9 @@
         ''' % (_opimpl, _opimpl.upper())).compile()
 
     for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not',
-                    'cast_ptr_to_int', 'cast_int_to_ptr',
+                    'cast_ptr_to_int', 'cast_float_to_int',
+                    'cast_int_to_float', 'float_neg', 'float_abs',
+                    'float_is_true',
                     ]:
         exec py.code.Source('''
             @arguments("box")
@@ -470,9 +475,8 @@
     def opimpl_ptr_iszero(self, box):
         self.execute(rop.OOISNULL, [box])
 
-    @arguments("box")
-    def opimpl_oononnull(self, box):
-        self.execute(rop.OONONNULL, [box])
+    opimpl_oononnull = opimpl_ptr_nonzero
+    opimpl_ooisnull = opimpl_ptr_iszero
 
     @arguments("box", "box")
     def opimpl_ptr_eq(self, box1, box2):
@@ -483,6 +487,7 @@
         self.execute(rop.OOISNOT, [box1, box2])
 
     opimpl_oois = opimpl_ptr_eq
+    opimpl_ooisnot = opimpl_ptr_ne
 
     @arguments("box", "descr")
     def opimpl_getfield_gc(self, box, fielddesc):
@@ -638,14 +643,27 @@
     def opimpl_residual_call(self, calldescr, varargs):
         return self.execute_with_exc(rop.CALL, varargs, descr=calldescr)
 
+    @arguments("varargs")
+    def opimpl_recursion_leave_prep(self, varargs):
+        warmrunnerstate = self.metainterp.staticdata.state
+        if warmrunnerstate.inlining:
+            num_green_args = self.metainterp.staticdata.num_green_args
+            greenkey = varargs[:num_green_args]
+            if warmrunnerstate.can_inline_callable(greenkey):
+                return False
+        leave_code = self.metainterp.staticdata.leave_code
+        if leave_code is None:
+            return False
+        return self.perform_call(leave_code, varargs)
+        
     @arguments("descr", "varargs")
     def opimpl_recursive_call(self, calldescr, varargs):
-        if self.metainterp.staticdata.options.inline:
+        warmrunnerstate = self.metainterp.staticdata.state
+        if warmrunnerstate.inlining:
             num_green_args = self.metainterp.staticdata.num_green_args
             portal_code = self.metainterp.staticdata.portal_code
             greenkey = varargs[1:num_green_args + 1]
-            if self.metainterp.staticdata.state.can_inline_callable(greenkey):
-                self.metainterp.in_recursion += 1
+            if warmrunnerstate.can_inline_callable(greenkey):
                 return self.perform_call(portal_code, varargs[1:])
         return self.execute_with_exc(rop.CALL, varargs, descr=calldescr)
 
@@ -1000,7 +1018,8 @@
     virtualizable_info = None
 
     def __init__(self, portal_graph, graphs, cpu, stats, options,
-                 optimizer=None, profile=None, warmrunnerdesc=None):
+                 optimizer=None, profile=None, warmrunnerdesc=None,
+                 leave_graph=None):
         self.portal_graph = portal_graph
         self.cpu = cpu
         self.stats = stats
@@ -1034,6 +1053,8 @@
         self.jit_starting_line = 'JIT starting (%s, %s)' % (optmodule,
                                                             backendmodule)
 
+        self.leave_graph = leave_graph
+
     def _freeze_(self):
         return True
 
@@ -1070,6 +1091,11 @@
         self._codewriter = codewriter.CodeWriter(self, policy)
         self.portal_code = self._codewriter.make_portal_bytecode(
             self.portal_graph)
+        self.leave_code = None
+        if self.leave_graph:
+            self.leave_code = self._codewriter.make_one_bytecode(
+                                                    (self.leave_graph, None),
+                                                    False)
         self._class_sizes = self._codewriter.class_sizes
 
     # ---------- construction-time interface ----------
@@ -1123,14 +1149,20 @@
     def newframe(self, jitcode):
         if not we_are_translated():
             self._debug_history.append(['enter', jitcode, None])
+        if jitcode is self.staticdata.portal_code:
+            self.in_recursion += 1
         f = MIFrame(self, jitcode)
         self.framestack.append(f)
         return f
 
-    def finishframe(self, resultbox):
+    def popframe(self):
         frame = self.framestack.pop()
         if frame.jitcode is self.staticdata.portal_code:
             self.in_recursion -= 1
+        return frame
+
+    def finishframe(self, resultbox):
+        frame = self.popframe()
         if not we_are_translated():
             self._debug_history.append(['leave', frame.jitcode, None])
         if self.framestack:
@@ -1148,6 +1180,8 @@
                 raise sd.DoneWithThisFrameInt(resultbox.getint())
             elif sd.result_type == 'ref':
                 raise sd.DoneWithThisFrameRef(self.cpu, resultbox.getref_base())
+            elif sd.result_type == 'float':
+                raise sd.DoneWithThisFrameFloat(resultbox.getfloat())
             else:
                 assert False
 
@@ -1171,11 +1205,29 @@
                 return True
             if not we_are_translated():
                 self._debug_history.append(['leave_exc', frame.jitcode, None])
-            self.framestack.pop()
+            self.popframe()
         if not self.is_blackholing():
             self.compile_exit_frame_with_exception(excvaluebox)
         raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base())
 
+    def check_recursion_invariant(self):
+        in_recursion = -1
+        for frame in self.framestack:
+            jitcode = frame.jitcode
+            if jitcode is self.staticdata.portal_code:
+                in_recursion += 1
+        if in_recursion != self.in_recursion:
+            print "in_recursion problem!!!"
+            print in_recursion, self.in_recursion
+            for frame in self.framestack:
+                jitcode = frame.jitcode
+                if jitcode is self.staticdata.portal_code:
+                    print "P",
+                else:
+                    print " ",
+                print jitcode.name
+            raise Exception
+
     def raise_overflow_error(self):
         etype, evalue = self.cpu.get_overflow_error()
         return self.finishframe_exception(
@@ -1189,6 +1241,7 @@
             self.cpu.ts.get_exc_value_box(evalue))
 
     def create_empty_history(self):
+        warmrunnerstate = self.staticdata.state
         self.history = history.History(self.cpu)
         if self.staticdata.stats is not None:
             self.staticdata.stats.history = self.history
@@ -1238,6 +1291,19 @@
             op.pc = self.framestack[-1].pc
             op.name = self.framestack[-1].jitcode.name
 
+    def switch_to_blackhole_if_trace_too_long(self):
+        if not self.is_blackholing():
+            warmrunnerstate = self.staticdata.state
+            if len(self.history.operations) > warmrunnerstate.trace_limit:
+                self.history = history.BlackHole(self.cpu)
+                if not we_are_translated():
+                    self.staticdata.stats.aborted_count += 1
+                    history.log.event('ABORTING TRACING' + self.history.extratext)
+                elif DEBUG:
+                    debug_print('~~~ ABORTING TRACING', self.history.extratext)
+                self.staticdata.profiler.end_tracing()
+                self.staticdata.profiler.start_blackhole()
+
     def _interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
         # a ContinueRunningNormally, or a GenerateMergePoint exception.
@@ -1249,6 +1315,9 @@
         try:
             while True:
                 self.framestack[-1].run_one_step()
+                self.switch_to_blackhole_if_trace_too_long()
+                if not we_are_translated():
+                    self.check_recursion_invariant()
         finally:
             if self.is_blackholing():
                 self.staticdata.profiler.end_blackhole()
@@ -1285,7 +1354,8 @@
             return self.designate_target_loop(gmp)
 
     def handle_guard_failure(self, exec_result, key):
-        self.initialize_state_from_guard_failure(exec_result)
+        from pypy.jit.metainterp.warmspot import ContinueRunningNormallyBase
+        resumedescr = self.initialize_state_from_guard_failure(exec_result)
         assert isinstance(key, compile.ResumeGuardDescr)
         top_history = key.find_toplevel_history()
         source_loop = top_history.source_link
@@ -1295,12 +1365,18 @@
         self.resumekey = key
         self.seen_can_enter_jit = False
         guard_op = key.get_guard_op()
+        started_as_blackhole = self.is_blackholing()
         try:
             self.prepare_resume_from_failure(guard_op.opnum)
             self.interpret()
             assert False, "should always raise"
         except GenerateMergePoint, gmp:
             return self.designate_target_loop(gmp)
+        except ContinueRunningNormallyBase:
+            if not started_as_blackhole:
+                warmrunnerstate = self.staticdata.state
+                warmrunnerstate.reset_counter_from_failure(resumedescr)
+            raise
 
     def forget_consts(self, boxes, startindex=0):
         for i in range(startindex, len(boxes)):
@@ -1456,6 +1532,9 @@
         elif sd.result_type == 'ref':
             exits = [exitbox]
             loops = sd.cpu.ts.loops_done_with_this_frame_ref
+        elif sd.result_type == 'float':
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_float
         else:
             assert False
         self.history.record(rop.JUMP, exits, None)
@@ -1489,7 +1568,7 @@
                                         *args[1:])
 
     def initialize_state_from_start(self, *args):
-        self.in_recursion = 0
+        self.in_recursion = -1 # always one portal around
         self.staticdata._setup_once()
         self.staticdata.profiler.start_tracing()
         self.create_empty_history()
@@ -1506,7 +1585,7 @@
 
     def initialize_state_from_guard_failure(self, guard_failure):
         # guard failure: rebuild a complete MIFrame stack
-        self.in_recursion = 0
+        self.in_recursion = -1 # always one portal around
         resumedescr = guard_failure.descr
         assert isinstance(resumedescr, compile.ResumeGuardDescr)
         warmrunnerstate = self.staticdata.state
@@ -1532,6 +1611,7 @@
             # the BlackHole is invalid because it doesn't start with
             # guard_failure.key.guard_op.suboperations, but that's fine
         self.rebuild_state_after_failure(resumedescr, guard_failure.args)
+        return resumedescr
 
     def initialize_virtualizable(self, original_boxes):
         vinfo = self.staticdata.virtualizable_info
@@ -1632,10 +1712,7 @@
             jitcode, pc, exception_target = resumereader.consume_frame_info()
             env = resumereader.consume_boxes()
             f = self.newframe(jitcode)
-            if jitcode is self.staticdata.portal_code:
-                self.in_recursion += 1
             f.setup_resume_at_op(pc, exception_target, env)
-        self.in_recursion -= 1 # always one portal around
 
     def check_synchronized_virtualizable(self):
         if not we_are_translated():

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py	Thu Sep 10 16:45:13 2009
@@ -126,7 +126,6 @@
     'OOSEND_PURE',    # ootype operation
     'CALL_PURE',
     #
-    'CAST_INT_TO_PTR',
     'CAST_PTR_TO_INT',
     'INT_ADD',
     'INT_SUB',
@@ -139,6 +138,15 @@
     'INT_RSHIFT',
     'INT_LSHIFT',
     'UINT_RSHIFT',
+    'FLOAT_ADD',
+    'FLOAT_SUB',
+    'FLOAT_MUL',
+    'FLOAT_TRUEDIV',
+    'FLOAT_NEG',
+    'FLOAT_ABS',
+    'FLOAT_IS_TRUE',
+    'CAST_FLOAT_TO_INT',
+    'CAST_INT_TO_FLOAT',
     #
     '_COMPARISON_FIRST',
     'INT_LT',
@@ -152,6 +160,12 @@
     'UINT_GT',
     'UINT_GE',
     '_COMPARISON_LAST',
+    'FLOAT_LT',          # maybe these ones should be comparisons too
+    'FLOAT_LE',
+    'FLOAT_EQ',
+    'FLOAT_NE',
+    'FLOAT_GT',
+    'FLOAT_GE',
     #
     'INT_IS_TRUE',
     'INT_NEG',

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py	Thu Sep 10 16:45:13 2009
@@ -186,9 +186,11 @@
 
     # ---------- malloc with del ----------
 
-    def _ll_0_alloc_with_del(RESULT):
-        return lltype.malloc(RESULT)
-    _ll_0_alloc_with_del.need_result_type = True
+    def _ll_1_alloc_with_del(RESULT, vtable):
+        p = lltype.malloc(RESULT)
+        lltype.cast_pointer(rclass.OBJECTPTR, p).typeptr = vtable
+        return p
+    _ll_1_alloc_with_del.need_result_type = True
 
 
 class OOtypeHelpers:
@@ -341,10 +343,6 @@
     else:
         raise Exception("oohash() of type %r" % (T,))
 
-def get_malloc_oopspec(op):
-    assert op.args[1].value == {'flavor': 'gc'}
-    return 'alloc_with_del', []
-
 
 RENAMED_ADT_NAME = {
     'list': {
@@ -375,8 +373,6 @@
         return get_oostring_oopspec(op)
     elif op.opname == 'oohash':
         return get_oohash_oopspec(op)
-    elif op.opname == 'malloc':         # for malloc with a __del__
-        return get_malloc_oopspec(op)
     else:
         raise ValueError(op.opname)
 

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py	Thu Sep 10 16:45:13 2009
@@ -97,6 +97,8 @@
         return vars
 
     def getvar(self, arg):
+        if not arg:
+            return ConstInt(0)
         try:
             return ConstInt(int(arg))
         except ValueError:
@@ -145,7 +147,10 @@
         argspec = line[num + 1:endnum]
         if not argspec.strip():
             return opnum, [], None
-        allargs = argspec.split(",")
+        if opname == 'debug_merge_point':
+            allargs = [argspec]
+        else:
+            allargs = argspec.split(",")
         args = []
         descr = None
         poss_descr = allargs[-1].strip()
@@ -195,8 +200,15 @@
         ops = []
         newlines = []
         for line in lines:
-            if '#' in line:
-                line = line[:line.index('#')]    # remove comment
+            # for simplicity comments are not allowed on
+            # debug_merge_point lines
+            if '#' in line and 'debug_merge_point(' not in line:
+                if line.lstrip()[0] == '#': # comment only
+                    continue
+                comm = line.rfind('#')
+                rpar = line.find(')') # assume there's a op(...)
+                if comm > rpar:
+                    line = line[:comm].rstrip()
             if not line.strip():
                 continue  # a comment or empty line
             newlines.append(line)

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py	Thu Sep 10 16:45:13 2009
@@ -1,4 +1,5 @@
 import py
+import sys
 from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
 from pypy.jit.backend.llgraph import runner
@@ -49,6 +50,8 @@
         assert get_stats().enter_count <= count
     def check_jumps(self, maxcount):
         assert get_stats().exec_jumps <= maxcount
+    def check_aborted_count(self, maxcount):
+        assert get_stats().aborted_count == maxcount
 
     def meta_interp(self, *args, **kwds):
         kwds['CPUClass'] = self.CPUClass
@@ -70,6 +73,8 @@
         class FakeWarmRunnerDesc:
             def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
                 pass
+
+            trace_limit = sys.maxint
         
         if policy is None:
             policy = JitPolicy()
@@ -89,6 +94,7 @@
         metainterp.staticdata.state = FakeWarmRunnerDesc()
         metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
         metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef
+        metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame
         self.metainterp = metainterp
         try:
             metainterp.compile_and_run_once(*args)
@@ -402,6 +408,24 @@
         assert res == 210
         self.check_history_(getfield_gc=0)
 
+    def test_setfield_bool(self):
+        class A:
+            def __init__(self):
+                self.flag = True
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'obj'])
+        def f(n):
+            obj = A()
+            res = False
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n, obj=obj)
+                myjitdriver.jit_merge_point(n=n, obj=obj)
+                obj.flag = False
+                n -= 1
+            return res
+        res = self.meta_interp(f, [7])
+        assert type(res) == bool
+        assert not res
+
     def test_switch_dict(self):
         def f(x):
             if   x == 1: return 61
@@ -915,16 +939,21 @@
         lltype.free(x, flavor='raw')
 
     def test_casts(self):
+        if not self.basic:
+            py.test.skip("test written in a style that "
+                         "means it's frontend only")
         from pypy.rpython.lltypesystem import lltype, llmemory
         
         TP = lltype.GcStruct('x')
         def f(p):
             n = lltype.cast_ptr_to_int(p)
-            return lltype.cast_int_to_ptr(lltype.Ptr(TP), n)
+            return n
 
         x = lltype.malloc(TP)
-        expected = lltype.cast_opaque_ptr(llmemory.GCREF, x)
-        assert self.interp_operations(f, [x]) == expected
+        res = self.interp_operations(f, [x])
+        expected = self.metainterp.cpu.do_cast_ptr_to_int(
+            [history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))]).value
+        assert res == expected
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     pass

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py	Thu Sep 10 16:45:13 2009
@@ -27,6 +27,33 @@
                           'guard_true': 1,
                           'jump': 1})
 
+    def test_class_of_allocated(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
+        class Foo:
+            def __del__(self):
+                pass
+            def f(self):
+                return self.meth()
+        class X(Foo):
+            def meth(self):
+                return 456
+        class Y(Foo):
+            def meth(self):
+                return 123
+        def f(n):
+            x = None
+            while n > 0:
+                myjitdriver.can_enter_jit(x=x, n=n)
+                myjitdriver.jit_merge_point(x=x, n=n)
+                x = X()
+                y = Y()
+                assert x.f() == 456
+                assert y.f() == 123
+                n -= 1
+            return 42
+        res = self.meta_interp(f, [20])
+        assert res == 42
+
 
 class TestLLtype(DelTests, LLJitMixin):
     def test_signal_action(self):
@@ -52,6 +79,6 @@
         self.check_loops(getfield_raw=1, call=0, call_pure=0)
 
 class TestOOtype(DelTests, OOJitMixin):
-    def test_del_keep_obj(self):
+    def setup_class(cls):
         py.test.skip("XXX dels are not implemented in the"
                      " static CLI or JVM backend")

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py	Thu Sep 10 16:45:13 2009
@@ -8,10 +8,10 @@
 def test_basic_parse():
     x = """
     [i0, i1]
-    i2 = int_add(i0, i1)
     # a comment
-    i3 = int_sub(i2, 3)
-    fail()
+    i2 = int_add(i0, i1)
+    i3 = int_sub(i2, 3) # another comment
+    fail() # (tricky)
     """
     loop = parse(x)
     assert len(loop.operations) == 3
@@ -146,10 +146,15 @@
     []
     debug_merge_point("info")
     debug_merge_point('info')
+    debug_merge_point('<some ('other,')> info')
+    debug_merge_point('(stuff) #1')
     '''
     loop = parse(x)
     assert loop.operations[0].args[0]._get_str() == 'info'
     assert loop.operations[1].args[0]._get_str() == 'info'
+    assert loop.operations[2].args[0]._get_str() == "<some ('other,')> info"
+    assert loop.operations[3].args[0]._get_str() == "(stuff) #1"
+    
 
 def test_descr_with_obj_print():
     x = '''

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py	Thu Sep 10 16:45:13 2009
@@ -19,11 +19,29 @@
 
     jitpolicy = policy.JitPolicy()
     translator = rtyper.annotator.translator
-    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator)
+    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+                                   True)
 
     funcs = [graph.func for graph in res]
     assert funcs == [i, f]
 
+def test_find_all_graphs_without_floats():
+    def g(x):
+        return int(x * 12.5)
+    def f(x):
+        return g(x) + 1
+    rtyper = support.annotate(f, [7])
+    jitpolicy = policy.JitPolicy()
+    translator = rtyper.annotator.translator
+    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+                                   supports_floats=True)
+    funcs = [graph.func for graph in res]
+    assert funcs == [f, g]
+    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+                                   supports_floats=False)
+    funcs = [graph.func for graph in res]
+    assert funcs == [f]
+
 def test_find_all_graphs_str_join():
     def i(x, y):
         return "hello".join([str(x), str(y), "bye"])
@@ -32,7 +50,8 @@
 
     jitpolicy = policy.JitPolicy()
     translator = rtyper.annotator.translator
-    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator)
+    res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+                                   True)
 
     funcs = [graph.func for graph in res]
     assert funcs[:1] == [i]

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py	Thu Sep 10 16:45:13 2009
@@ -1,7 +1,7 @@
 
 # some unit tests for the bytecode decoding
 
-from pypy.jit.metainterp import pyjitpl, codewriter
+from pypy.jit.metainterp import pyjitpl, codewriter, resoperation
 
 def make_frame(code):
     bytecode = codewriter.JitCode("hello")
@@ -24,3 +24,11 @@
 
     frame = make_frame("\x01")
     assert frame.load_bool()
+
+def test_simple_opimpl_exist():
+    rop = resoperation.rop
+    for opnum, opname in resoperation.opname.items():
+        if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE):
+            continue
+        if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST:
+            assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py	Thu Sep 10 16:45:13 2009
@@ -1,10 +1,10 @@
 import py
-from pypy.rlib.jit import JitDriver
+from pypy.rlib.jit import JitDriver, we_are_jitted
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp import simple_optimize
 from pypy.jit.metainterp.policy import StopAtXPolicy
 from pypy.rpython.annlowlevel import hlstr
-from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit
+from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats
 
 class RecursiveTests:
 
@@ -213,10 +213,239 @@
         res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
         assert res == 0
 
+    def test_exception_in_inlined_function(self):
+        from pypy.rpython.annlowlevel import hlstr
+        def p(code, pc):
+            code = hlstr(code)
+            return "%s %d %s" % (code, pc, code[pc])
+        def c(code, pc):
+            return "l" not in hlstr(code)
+        myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'],
+                                get_printable_location=p, can_inline=c)
+
+        class Exc(Exception):
+            pass
+        
+        def f(code, n):
+            pc = 0
+            while pc < len(code):
+
+                myjitdriver.jit_merge_point(n=n, code=code, pc=pc)
+                op = code[pc]
+                if op == "-":
+                    n -= 1
+                elif op == "c":
+                    try:
+                        n = f("---i---", n)
+                    except Exc:
+                        pass
+                elif op == "i":
+                    if n % 5 == 1:
+                        raise Exc
+                elif op == "l":
+                    if n > 0:
+                        myjitdriver.can_enter_jit(n=n, code=code, pc=0)
+                        pc = 0
+                        continue
+                else:
+                    assert 0
+                pc += 1
+            return n
+        def main(n):
+            return f("c-l", n)
+        res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+        assert res == main(100)
+
+    def test_recurse_during_blackholing(self):
+        # this passes, if the blackholing shortcut for calls is turned off
+        # it fails, it is very delicate in terms of parameters,
+        # bridge/loop creation order
+        from pypy.rpython.annlowlevel import hlstr
+        def p(code, pc):
+            code = hlstr(code)
+            return "%s %d %s" % (code, pc, code[pc])
+        def c(code, pc):
+            return "l" not in hlstr(code)
+        myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'],
+                                get_printable_location=p, can_inline=c)
+        
+        def f(code, n):
+            pc = 0
+            while pc < len(code):
+
+                myjitdriver.jit_merge_point(n=n, code=code, pc=pc)
+                op = code[pc]
+                if op == "-":
+                    n -= 1
+                elif op == "c":
+                    if n < 70 and n % 3 == 1:
+                        print "F"
+                        n = f("--", n)
+                elif op == "l":
+                    if n > 0:
+                        myjitdriver.can_enter_jit(n=n, code=code, pc=0)
+                        pc = 0
+                        continue
+                else:
+                    assert 0
+                pc += 1
+            return n
+        def main(n):
+            myjitdriver.set_param('threshold', 3)
+            myjitdriver.set_param('trace_eagerness', 5)            
+            return f("c-l", n)
+        expected = main(100)
+        res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+        assert res == expected
+
+    def check_max_trace_length(self, length):
+        for loop in get_stats().loops:
+            assert len(loop.operations) <= length + 5 # because we only check once per metainterp bytecode
+            for op in loop.operations:
+                if op.is_guard():
+                    assert len(op.suboperations) <= length + 5
+
+    def test_inline_trace_limit(self):
+        myjitdriver = JitDriver(greens=[], reds=['n'])
+        def recursive(n):
+            if n > 0:
+                return recursive(n - 1) + 1
+            return 0
+        def loop(n):            
+            myjitdriver.set_param("threshold", 10)
+            pc = 0
+            while n:
+                myjitdriver.can_enter_jit(n=n)
+                myjitdriver.jit_merge_point(n=n)
+                n = recursive(n)
+                n -= 1
+            return n
+        TRACE_LIMIT = 66
+        res = self.meta_interp(loop, [100], optimizer=simple_optimize, inline=True, trace_limit=TRACE_LIMIT)
+        assert res == 0
+        self.check_max_trace_length(TRACE_LIMIT)
+        self.check_enter_count(15) # maybe
+        self.check_aborted_count(7)
+
+    def test_trace_limit_bridge(self):
+        def recursive(n):
+            if n > 0:
+                return recursive(n - 1) + 1
+            return 0
+        myjitdriver = JitDriver(greens=[], reds=['n'])
+        def loop(n):
+            myjitdriver.set_param("threshold", 4)
+            myjitdriver.set_param("trace_eagerness", 2)
+            while n:
+                myjitdriver.can_enter_jit(n=n)
+                myjitdriver.jit_merge_point(n=n)
+                if n % 5 == 0:
+                    n -= 1
+                if n < 50:
+                    n = recursive(n)
+                n -= 1
+        TRACE_LIMIT = 20
+        res = self.meta_interp(loop, [100], optimizer=simple_optimize, inline=True, trace_limit=TRACE_LIMIT)
+        self.check_max_trace_length(TRACE_LIMIT)
+        self.check_aborted_count(8)
+        self.check_enter_count_at_most(30)
+
+    def test_set_param_inlining(self):
+        myjitdriver = JitDriver(greens=[], reds=['n', 'recurse'])
+        def loop(n, recurse=False):
+            while n:
+                myjitdriver.jit_merge_point(n=n, recurse=recurse)
+                n -= 1
+                if not recurse:
+                    loop(10, True)
+                    myjitdriver.can_enter_jit(n=n, recurse=recurse)
+            return n
+        TRACE_LIMIT = 66
+ 
+        def main(inline):
+            myjitdriver.set_param("threshold", 10)
+            if inline:
+                myjitdriver.set_param('inlining', True)
+            else:
+                myjitdriver.set_param('inlining', False)
+            return loop(100)
+
+        res = self.meta_interp(main, [0], optimizer=simple_optimize, trace_limit=TRACE_LIMIT)
+        self.check_loops(call=1)
+
+        res = self.meta_interp(main, [1], optimizer=simple_optimize, trace_limit=TRACE_LIMIT)
+        self.check_loops(call=0)
+
+    def test_leave_jit_hook(self):
+        from pypy.rpython.annlowlevel import hlstr
+        def p(code, pc):
+            code = hlstr(code)
+            return "%s %d %s" % (code, pc, code[pc])
+        def c(code, pc):
+            return "L" not in hlstr(code)
+
+        def leave(code, pc, frame):
+            frame.hookcalled = True
+
+        class ExpectedHook(Exception):
+            pass
+        class UnexpectedHook(Exception):
+            pass
+
+        myjitdriver = JitDriver(greens=['code', 'pc'], reds=['self'],
+                                get_printable_location=p, can_inline=c,
+                                leave=leave)
+        class Frame(object):
+            hookcalled = True
+            
+            def __init__(self, n):
+                self.n = n
+                self.hookcalled = False
+            def f(self, code):
+                pc = 0
+                while pc < len(code):
+
+                    myjitdriver.jit_merge_point(self=self, code=code, pc=pc)
+                    op = code[pc]
+                    if op == "-":
+                        self.n -= 1
+                    elif op == "c":
+                        frame = Frame(self.n)
+                        self.n = frame.f("---i---")
+                        if we_are_jitted():
+                            if frame.hookcalled:
+                                raise UnexpectedHook
+                    elif op == "C":
+                        frame = Frame(self.n)
+                        self.n = frame.f("cL")
+                        if we_are_jitted():
+                            if not frame.hookcalled:
+                                raise ExpectedHook
+                    elif op == "i":
+                        if self.n % 5 == 1:
+                            return self.n
+                    elif op == "l":
+                        if self.n > 0:
+                            myjitdriver.can_enter_jit(self=self, code=code, pc=0)
+                            pc = 0
+                            continue
+                    elif op == "L":
+                        if self.n > 50:
+                            myjitdriver.can_enter_jit(self=self, code=code, pc=0)
+                            pc = 0
+                            continue
+                    else:
+                        assert 0
+                    pc += 1
+                return self.n
+        def main(n):
+            frame = Frame(n)
+            return frame.f("C-l")
+        res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+        assert res == main(100)
 
 class TestLLtype(RecursiveTests, LLJitMixin):
     pass
 
 class TestOOtype(RecursiveTests, OOJitMixin):
-    def test_simple_recursion_with_exc(self):
-        py.test.skip("Fails")
+    pass

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py	Thu Sep 10 16:45:13 2009
@@ -4,6 +4,7 @@
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
 from pypy.rpython.lltypesystem import lltype, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.ootypesystem import ootype
 from pypy.jit.metainterp import heaptracker
 
 class VirtualTests:
@@ -272,9 +273,9 @@
             return f
 
         res = self.meta_interp(f, [21], repeat=7)
-        # hack
-        assert (getattr(res, "inst_value", -100) == f(21).value or
-                getattr(res, "value", -100) == f(21).value)
+
+        fieldname = self._field_prefix + 'value'
+        assert getattr(res, fieldname, -100) == f(21).value
 
         self.check_tree_loop_count(2)      # the loop and the entry path
         # we get:
@@ -285,9 +286,6 @@
         self.check_enter_count(4)
 
 
-##class TestOOtype(VirtualTests, OOJitMixin):
-##    _new = staticmethod(ootype.new)
-
 # ____________________________________________________________
 # Run 1: all the tests instantiate a real RPython class
 
@@ -296,10 +294,47 @@
 
 class TestLLtype_Instance(VirtualTests, LLJitMixin):
     _new_op = 'new_with_vtable'
+    _field_prefix = 'inst_'
+    
+    @staticmethod
+    def _new():
+        return MyClass()
+
+    def test_class_with_default_fields(self):
+        class MyClass:
+            value = 2
+
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'res'])
+        def f(n):
+            res = 0
+            node = MyClass()
+            node.value = n # so that the annotator doesn't think that value is constant
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n, res=res)
+                myjitdriver.jit_merge_point(n=n, res=res)
+                node = MyClass()
+                res += node.value
+                n -= 1
+            return res
+        assert f(10) == 20
+        res = self.meta_interp(f, [10])
+        assert res == 20
+        self.check_loop_count(1)
+        self.check_loops(new=0, new_with_vtable=0,
+                                getfield_gc=0, setfield_gc=0)
+
+
+
+class TestOOtype_Instance(VirtualTests, OOJitMixin):
+    _new_op = 'new_with_vtable'
+    _field_prefix = 'o'
+    
     @staticmethod
     def _new():
         return MyClass()
 
+    test_class_with_default_fields = TestLLtype_Instance.test_class_with_default_fields.im_func
+
 # ____________________________________________________________
 # Run 2: all the tests use lltype.malloc to make a NODE
 
@@ -308,11 +343,25 @@
 
 class TestLLtype_NotObject(VirtualTests, LLJitMixin):
     _new_op = 'new'
-
+    _field_prefix = ''
+    
     @staticmethod
     def _new():
         return lltype.malloc(NODE)
 
+
+OONODE = ootype.Instance('NODE', ootype.ROOT, {})
+OONODE._add_fields({'value': ootype.Signed,
+                    'extra': ootype.Signed})
+
+class TestOOtype_NotObject(VirtualTests, OOJitMixin):
+    _new_op = 'new_with_vtable'
+    _field_prefix = ''
+    
+    @staticmethod
+    def _new():
+        return ootype.new(OONODE)
+
 # ____________________________________________________________
 # Run 3: all the tests use lltype.malloc to make a NODE2
 # (same as Run 2 but it is part of the OBJECT hierarchy)
@@ -326,6 +375,8 @@
 
 class TestLLtype_Object(VirtualTests, LLJitMixin):
     _new_op = 'new_with_vtable'
+    _field_prefix = ''
+    
     @staticmethod
     def _new():
         p = lltype.malloc(NODE2)

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py	Thu Sep 10 16:45:13 2009
@@ -90,7 +90,9 @@
         pass
     def check_enter_count_at_most(self, count):
         pass
-    def check_jumps(self, maxcount):
+    def check_jumps(self, maxcount):        
+        pass
+    def check_aborted_count(self, count):
         pass
 
     def interp_operations(self, *args, **kwds):

Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py	Thu Sep 10 16:45:13 2009
@@ -26,7 +26,9 @@
 # ____________________________________________________________
 # Bootstrapping
 
-def apply_jit(translator, backend_name="auto", debug_level="steps", **kwds):
+def apply_jit(translator, backend_name="auto", debug_level="steps",
+              inline=False,
+              **kwds):
     if 'CPUClass' not in kwds:
         from pypy.jit.backend.detect_cpu import getcpuclass
         kwds['CPUClass'] = getcpuclass(backend_name)
@@ -38,9 +40,9 @@
     warmrunnerdesc = WarmRunnerDesc(translator,
                                     translate_support_code=True,
                                     listops=True,
-                                    #inline=True,
                                     profile=profile,
                                     **kwds)
+    warmrunnerdesc.state.set_param_inlining(inline)    
     warmrunnerdesc.finish()
     translator.warmrunnerdesc = warmrunnerdesc    # for later debugging
 
@@ -52,13 +54,15 @@
     clear_tcache()
     return jittify_and_run(interp, graph, args, backendopt=backendopt, **kwds)
 
-def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None, backendopt=False,
-                    **kwds):
+def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None, backendopt=False, trace_limit=sys.maxint,
+                    inline=False, **kwds):
     translator = interp.typer.annotator.translator
     translator.config.translation.gc = "boehm"
     warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds)
     warmrunnerdesc.state.set_param_threshold(3)          # for tests
     warmrunnerdesc.state.set_param_trace_eagerness(2)    # for tests
+    warmrunnerdesc.state.set_param_trace_limit(trace_limit)
+    warmrunnerdesc.state.set_param_inlining(inline)
     warmrunnerdesc.state.create_tables_now()             # for tests
     if hash_bits:
         warmrunnerdesc.state.set_param_hash_bits(hash_bits)
@@ -120,6 +124,9 @@
 class JitException(Exception):
     _go_through_llinterp_uncaught_ = True     # ugh
 
+class ContinueRunningNormallyBase(JitException):
+    pass
+
 class CannotInlineCanEnterJit(JitException):
     pass
 
@@ -127,18 +134,21 @@
 
 class WarmRunnerDesc:
 
-    def __init__(self, translator, policy=None, backendopt=True, **kwds):
+    def __init__(self, translator, policy=None, backendopt=True, CPUClass=None,
+                 **kwds):
         pyjitpl._warmrunnerdesc = self   # this is a global for debugging only!
         if policy is None:
             policy = JitPolicy()
         self.set_translator(translator)
         self.find_portal()
-        graphs = find_all_graphs(self.portal_graph, policy, self.translator)
+        self.make_leave_jit_graph()
+        graphs = find_all_graphs(self.portal_graph, policy, self.translator,
+                                 CPUClass.supports_floats)
         self.check_access_directly_sanity(graphs)
         if backendopt:
             self.prejit_optimizations(policy, graphs)
 
-        self.build_meta_interp(**kwds)
+        self.build_meta_interp(CPUClass, **kwds)
         self.make_args_specification()
         self.rewrite_jit_merge_point()
         self.make_driverhook_graph()
@@ -206,7 +216,7 @@
                               remove_asserts=True,
                               really_remove_asserts=True)
 
-    def build_meta_interp(self, CPUClass=None, translate_support_code=False,
+    def build_meta_interp(self, CPUClass, translate_support_code=False,
                           view="auto", optimizer=None, profile=None, **kwds):
         assert CPUClass is not None
         opt = history.Options(**kwds)
@@ -224,7 +234,8 @@
                                                   self.stats, opt,
                                                   optimizer=optimizer,
                                                   profile=profile,
-                                                  warmrunnerdesc=self)
+                                                  warmrunnerdesc=self,
+                                                  leave_graph=self.leave_graph)
 
     def make_enter_function(self):
         WarmEnterState = make_state_class(self)
@@ -259,6 +270,21 @@
 
         self.maybe_enter_jit_fn = maybe_enter_jit
 
+    def make_leave_jit_graph(self):
+        self.leave_graph = None
+        if self.jitdriver.leave:
+            graph, block, index = self.jit_merge_point_pos
+            op = block.operations[index]
+            args = op.args[2:]
+            s_binding = self.translator.annotator.binding
+            args_s = [s_binding(v) for v in args]            
+            from pypy.annotation import model as annmodel
+            annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
+            s_result = annmodel.s_None
+            self.leave_graph = annhelper.getgraph(self.jitdriver.leave,
+                                                  args_s, s_result)
+            annhelper.finish()
+        
     def make_driverhook_graph(self):
         self.can_inline_ptr = self._make_hook_graph(
             self.jitdriver.can_inline, bool)
@@ -393,6 +419,13 @@
             def __str__(self):
                 return 'DoneWithThisFrameRef(%s)' % (self.result,)
 
+        class DoneWithThisFrameFloat(JitException):
+            def __init__(self, cpu, result):
+                assert lltype.typeOf(result) is lltype.Float
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameFloat(%s)' % (self.result,)
+
         class ExitFrameWithExceptionRef(JitException):
             def __init__(self, cpu, value):
                 assert lltype.typeOf(value) == cpu.ts.BASETYPE
@@ -400,7 +433,7 @@
             def __str__(self):
                 return 'ExitFrameWithExceptionRef(%s)' % (self.value,)
 
-        class ContinueRunningNormally(JitException):
+        class ContinueRunningNormally(ContinueRunningNormallyBase):
             def __init__(self, argboxes):
                 # accepts boxes as argument, but unpacks them immediately
                 # before we raise the exception -- the boxes' values will
@@ -416,11 +449,13 @@
         self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
         self.DoneWithThisFrameInt = DoneWithThisFrameInt
         self.DoneWithThisFrameRef = DoneWithThisFrameRef
+        self.DoneWithThisFrameFloat = DoneWithThisFrameFloat
         self.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
         self.ContinueRunningNormally = ContinueRunningNormally
         self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
         self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
         self.metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+        self.metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrameFloat
         self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
         self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
         rtyper = self.translator.rtyper
@@ -447,6 +482,9 @@
                 except DoneWithThisFrameRef, e:
                     assert result_kind == 'ref'
                     return ts.cast_from_ref(RESULT, e.result)
+                except DoneWithThisFrameFloat, e:
+                    assert result_kind == 'float'
+                    return e.result
                 except ExitFrameWithExceptionRef, e:
                     value = ts.cast_to_baseclass(e.value)
                     if not we_are_translated():
@@ -510,7 +548,7 @@
             op.args[:3] = [closures[funcname]]
 
 
-def find_all_graphs(portal, policy, translator):
+def find_all_graphs(portal, policy, translator, supports_floats):
     from pypy.translator.simplify import get_graph
     all_graphs = [portal]
     seen = set([portal])
@@ -520,13 +558,13 @@
         for _, op in top_graph.iterblockops():
             if op.opname not in ("direct_call", "indirect_call", "oosend"):
                 continue
-            kind = policy.guess_call_kind(op)
+            kind = policy.guess_call_kind(op, supports_floats)
             if kind != "regular":
                 continue
-            for graph in policy.graphs_from(op):
+            for graph in policy.graphs_from(op, supports_floats):
                 if graph in seen:
                     continue
-                if policy.look_inside_graph(graph):
+                if policy.look_inside_graph(graph, supports_floats):
                     todo.append(graph)
                     all_graphs.append(graph)
                     seen.add(graph)
@@ -552,6 +590,8 @@
         return box.getref(TYPE)
     if isinstance(TYPE, ootype.OOType):
         return box.getref(TYPE)
+    if TYPE == lltype.Float:
+        return box.getfloat()
     else:
         return lltype.cast_primitive(TYPE, box.getint())
 unwrap._annspecialcase_ = 'specialize:arg(0)'
@@ -574,6 +614,11 @@
             return history.ConstObj(value)
         else:
             return history.BoxObj(value)
+    elif isinstance(value, float):
+        if in_const_box:
+            return history.ConstFloat(value)
+        else:
+            return history.BoxFloat(value)
     else:
         value = intmask(value)
     if in_const_box:
@@ -683,6 +728,9 @@
         elif typecode == 'int':
             intvalue = lltype.cast_primitive(lltype.Signed, value)
             cpu.set_future_value_int(j, intvalue)
+        elif typecode == 'float':
+            assert isinstance(value, float)
+            cpu.set_future_value_float(j, value)
         else:
             assert False
     set_future_value._annspecialcase_ = 'specialize:ll_and_arg(2)'
@@ -704,6 +752,12 @@
         def set_param_trace_eagerness(self, value):
             self.trace_eagerness = value
 
+        def set_param_trace_limit(self, value):
+            self.trace_limit = value
+
+        def set_param_inlining(self, value):
+            self.inlining = value
+
         def set_param_hash_bits(self, value):
             if value < 1:
                 value = 1
@@ -748,7 +802,13 @@
                     self.create_tables_now()
                     return
                 metainterp = MetaInterp(metainterp_sd)
-                loop = metainterp.compile_and_run_once(*args)
+                try:
+                    loop = metainterp.compile_and_run_once(*args)
+                except warmrunnerdesc.ContinueRunningNormally:
+                    # the trace got too long, reset the counter
+                    self.mccounters[argshash] = 0
+                    raise
+
             else:
                 # machine code was already compiled for these greenargs
                 # (or we have a hash collision)
@@ -837,6 +897,9 @@
             key.counter += 1
             return key.counter >= self.trace_eagerness
 
+        def reset_counter_from_failure(self, key):
+            key.counter = 0
+
         def attach_unoptimized_bridge_from_interp(self, greenkey, bridge):
             greenargs = self.unwrap_greenkey(greenkey)
             newcell = MachineCodeEntryPoint(bridge, *greenargs)

Modified: pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py	(original)
+++ pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py	Thu Sep 10 16:45:13 2009
@@ -38,6 +38,7 @@
 
     print 'warmspot.jittify_and_run() started...'
     from pypy.jit.backend.llgraph.runner import LLtypeCPU
+    LLtypeCPU.supports_floats = False    # for now
     policy = PyPyJitPolicy(interp.typer.annotator.translator)
     option.view = True
     warmspot.jittify_and_run(interp, graph, [], policy=policy,

Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py	Thu Sep 10 16:45:13 2009
@@ -27,23 +27,11 @@
         'raw_input'     : 'app_io.raw_input',
         'input'         : 'app_io.input',
 
-        'sum'           : 'app_functional.sum',
         'apply'         : 'app_functional.apply',
-        'map'           : 'app_functional.map',
-        'filter'        : 'app_functional.filter',
-        'zip'           : 'app_functional.zip',
-        'reduce'        : 'app_functional.reduce',
         #'range'         : 'app_functional.range',
         # redirected to functional.py, applevel version
         # is still needed and should stay where it is.
-        'min'           : 'app_functional.min',
-        'max'           : 'app_functional.max',
-        'enumerate'     : 'app_functional.enumerate',
         'sorted'        : 'app_functional.sorted',
-        'reversed'      : 'app_functional.reversed',
-        '_install_pickle_support_for_reversed_iterator':
-        'app_functional._install_pickle_support_for_reversed_iterator',
-
         'globals'       : 'app_inspect.globals',
         'locals'        : 'app_inspect.locals',
         'vars'          : 'app_inspect.vars',
@@ -106,8 +94,17 @@
 
         'range'         : 'functional.range_int',
         'xrange'        : 'functional.W_XRange',
+        'enumerate'     : 'functional.W_Enumerate',
         'all'           : 'functional.all',
         'any'           : 'functional.any',
+        'min'           : 'functional.min',
+        'max'           : 'functional.max',
+        'sum'           : 'functional.sum',
+        'map'           : 'functional.map',
+        'zip'           : 'functional.zip',
+        'reduce'        : 'functional.reduce',
+        'reversed'      : 'functional.reversed',
+        'filter'        : 'functional.filter',
         'super'         : 'descriptor.W_Super',
         'staticmethod'  : 'descriptor.StaticMethod',
         'classmethod'   : 'descriptor.ClassMethod',

Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py	Thu Sep 10 16:45:13 2009
@@ -3,151 +3,12 @@
 functional programming.
 """
 
-
-def sum(sequence, total=0):
-    """sum(sequence, start=0) -> value
-
-Returns the sum of a sequence of numbers (NOT strings) plus the value
-of parameter 'start'.  When the sequence is empty, returns start."""
-    # must forbid "summing" strings, per specs of built-in 'sum'
-    if isinstance(total, str): raise TypeError
-    for item in sequence:
-        total = total + item
-    return total
-
 # ____________________________________________________________
 
 def apply(function, args=(), kwds={}):
     """call a function (or other callable object) and return its result"""
     return function(*args, **kwds)
 
-def map(function, *collections):
-    """does 3 separate things, hence this enormous docstring.
-       1.  if function is None, return a list of tuples, each with one
-           item from each collection.  If the collections have different
-           lengths,  shorter ones are padded with None.
-
-       2.  if function is not None, and there is only one collection,
-           apply function to every item in the collection and return a
-           list of the results.
-
-       3.  if function is not None, and there are several collections,
-           repeatedly call the function with one argument from each
-           collection.  If the collections have different lengths,
-           shorter ones are padded with None
-    """
-
-    if len(collections) == 0:
-        raise TypeError, "map() requires at least one sequence"
-
-    if len(collections) == 1:
-        #it's the most common case, so make it faster
-        if function is None:
-            return list(collections[0])
-        return [function(x) for x in collections[0]]
-
-    iterators = [ iter(collection) for collection in collections ]
-    res = []
-    while 1:
-        cont = False     #is any collection not empty?
-        args = []
-        for iterator in iterators:
-            try:
-                elem = iterator.next()
-                cont = True
-            except StopIteration:
-                elem = None
-            args.append(elem)
-        if cont:
-            if function is None:
-                res.append(tuple(args))
-            else:
-                res.append(function(*args))
-        else:
-            return res
-
-def filterstring(function, collection, str_type):
-    if function is None and type(collection) is str_type:
-        return collection
-    res = []
-    for i in xrange(len(collection)):
-        c = collection[i]
-        if function is None or function(c):
-            if not isinstance(c, str_type):
-                raise TypeError("can't filter %s to %s: __getitem__ returned different type", str_type.__name__, str_type.__name__)
-            res.append(c)
-    return str_type().join(res)
-
-def filtertuple(function, collection):
-    if function is None:
-        function = bool
-    res = []
-    for i in xrange(len(collection)):
-        c = collection[i]
-        if function(c):
-            res.append(c)
-    return tuple(res)
-
-def filter(function, collection):
-    """construct a list of those elements of collection for which function
-       is True.  If function is None, then return the items in the sequence
-       which are True."""
-    if isinstance(collection, str):
-        return filterstring(function, collection, str)
-    elif isinstance(collection, unicode):
-        return filterstring(function, collection, unicode)
-    elif isinstance(collection, tuple):
-        return filtertuple(function, collection)
-
-    if function is None:
-        return [item for item in collection if item]
-    else:
-        return [item for item in collection if function(item)]
-
-def zip(*collections):
-    """return a list of tuples, where the nth tuple contains every
-       nth item of each collection.  If the collections have different
-       lengths, zip returns a list as long as the shortest collection,
-       ignoring the trailing items in the other collections."""
-
-    if len(collections) == 0:
-        import sys
-        if sys.version_info < (2,4):
-            raise TypeError("zip() requires at least one sequence")
-        return []
-    res = []
-    iterators = [ iter(collection) for collection in collections ]
-    while 1:
-        try:
-            elems = []
-            for iterator in iterators:
-                elems.append(iterator.next())
-            res.append(tuple(elems))
-        except StopIteration:
-            return res
-
-def reduce(function, seq, *initialt):
-    """ Apply function of two arguments cumulatively to the items of
-        sequence, from left to right, so as to reduce the sequence to a
-        single value.  Optionally begin with an initial value."""
-
-    seqiter = iter(seq)
-    if initialt:
-       initial, = initialt
-    else:
-       try:
-          initial = seqiter.next()
-       except StopIteration:
-          raise TypeError, "reduce() of empty sequence with no initial value"
-    while 1:
-        try:
-            arg = seqiter.next()
-        except StopIteration:
-            break
-        initial = function(initial, arg)
-
-    return initial
-
 # ____________________________________________________________
 
 """
@@ -206,135 +67,10 @@
 
 # ____________________________________________________________
 
-
-def _identity(arg):
-    return arg
-
-
-def min(*arr, **kwargs):
-    """return the smallest number in a list,
-    or its smallest argument if more than one is given."""
-    from operator import gt
-
-    return min_max(gt, "min", *arr, **kwargs)
-
-def min_max(comp, funcname, *arr, **kwargs):
-    key = kwargs.pop("key", _identity)
-    if len(kwargs):
-        raise TypeError, '%s() got an unexpected keyword argument' % funcname
-
-    if not arr:
-        raise TypeError, '%s() takes at least one argument' % funcname
-
-    if len(arr) == 1:
-        arr = arr[0]
-
-    iterator = iter(arr)
-    try:
-        min_max_val = iterator.next()
-    except StopIteration:
-        raise ValueError, '%s() arg is an empty sequence' % funcname
-
-    keyed_min_max_val = key(min_max_val)
-
-    for i in iterator:
-        keyed = key(i)
-        if comp(keyed_min_max_val, keyed):
-            min_max_val = i
-            keyed_min_max_val = keyed
-    return min_max_val
-
-def max(*arr, **kwargs):
-    """return the largest number in a list,
-    or its largest argument if more than one is given."""
-    from operator import lt
-
-    return min_max(lt, "max", *arr, **kwargs)
-
-class enumerate(object):
-    """enumerate(iterable) -> iterator for (index, value) of iterable.
-
-Return an enumerate object.  iterable must be an other object that supports
-iteration.  The enumerate object yields pairs containing a count (from
-zero) and a value yielded by the iterable argument.  enumerate is useful
-for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."""
-
-    def __init__(self, collection):
-        self._iter = iter(collection)
-        self._index = 0
-    
-    def next(self):
-        try:
-            next = self._iter.next
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s object has no next() method' %
-                            (type(self._iter).__name__,))
-        result = self._index, next()
-        self._index += 1
-        return result
-    
-    def __iter__(self):
-        return self
-
-
-# ____________________________________________________________
-
 def sorted(lst, cmp=None, key=None, reverse=None):
     "sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"
     sorted_lst = list(lst)
     sorted_lst.sort(cmp, key, reverse)
     return sorted_lst
 
-def reversed(sequence):
-    "reversed(sequence) -> reverse iterator over values of the sequence"
-    if hasattr(sequence, '__reversed__'):
-        return sequence.__reversed__()
-    if not hasattr(sequence, '__getitem__'):
-        raise TypeError("argument to reversed() must be a sequence")
-    return reversed_iterator(sequence)
-
-
-class reversed_iterator(object):
-
-    def __init__(self, seq):
-        self.seq = seq
-        self.remaining = len(seq)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        if self.remaining > len(self.seq):
-            self.remaining = 0
-        i = self.remaining
-        if i > 0:
-            i -= 1
-            item = self.seq[i]
-            self.remaining = i
-            return item
-        raise StopIteration
-
-# XXX __length_hint__()
-##    def __len__(self):
-##        if self.remaining > len(self.seq):
-##            self.remaining = 0
-##        return self.remaining
-
-    def __reduce__(self):
-        tup = (self.seq, self.remaining)
-        return (make_reversed_iterator, tup)
-
-def make_reversed_iterator(seq, remaining):
-    ri = reversed_iterator.__new__(reversed_iterator)
-    ri.seq = seq
-    #or "ri = reversed_iterator(seq)" but that executes len(seq)
-    ri.remaining = remaining
-    return ri
-
-def _install_pickle_support_for_reversed_iterator():
-    import _pickle_support
-    make_reversed_iterator.__module__ = '_pickle_support'
-    _pickle_support.make_reversed_iterator = make_reversed_iterator
-
 

Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py	Thu Sep 10 16:45:13 2009
@@ -8,7 +8,9 @@
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.argument import Arguments
 from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.objectmodel import specialize
 from pypy.module.__builtin__.app_functional import range as app_range
 from inspect import getsource, getfile
 
@@ -100,7 +102,239 @@
         return W_ListMultiObject(space, impl)
 
 
+ at specialize.arg(2)
+def min_max(space, arguments, implementation_of):
+    if implementation_of == "max":
+        compare = space.gt
+    else:
+        compare = space.lt
+    args, kwargs = arguments.unpack()
+    if len(args) > 1:
+        w_sequence = space.newtuple(args)
+    elif len(args):
+        w_sequence = args[0]
+    else:
+        msg = "%s() expects at least one argument" % (implementation_of,)
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    try:
+        w_key = kwargs["key"]
+    except KeyError:
+        w_key = None
+    else:
+        del kwargs["key"]
+    if kwargs:
+        msg = "%s() got unexpected keyword argument" % (implementation_of,)
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    w_iter = space.iter(w_sequence)
+    w_max_item = None
+    w_max_val = None
+    while True:
+        try:
+            w_item = space.next(w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break
+        if w_key is not None:
+            w_compare_with = space.call_function(w_key, w_item)
+        else:
+            w_compare_with = w_item
+        if w_max_item is None or \
+                space.is_true(compare(w_compare_with, w_max_val)):
+            w_max_item = w_item
+            w_max_val = w_compare_with
+    if w_max_item is None:
+        msg = "arg is an empty sequence"
+        raise OperationError(space.w_ValueError, space.wrap(msg))
+    return w_max_item
+
+def max(space, __args__):
+    """Return the largest item in a sequence.
+
+    If more than one argument is passed, return the maximum of them.
+    """
+    return min_max(space, __args__, "max")
+max.unwrap_spec = [ObjSpace, Arguments]
+
+def min(space, __args__):
+    """Return the smallest item in a sequence.
+
+    If more than one argument is passed, return the minimum of them.
+    """
+    return min_max(space, __args__, "min")
+min.unwrap_spec = [ObjSpace, Arguments]
+
+def map(space, w_func, collections_w):
+    """does 3 separate things, hence this enormous docstring.
+       1.  if function is None, return a list of tuples, each with one
+           item from each collection.  If the collections have different
+           lengths,  shorter ones are padded with None.
+
+       2.  if function is not None, and there is only one collection,
+           apply function to every item in the collection and return a
+           list of the results.
+
+       3.  if function is not None, and there are several collections,
+           repeatedly call the function with one argument from each
+           collection.  If the collections have different lengths,
+           shorter ones are padded with None
+    """
+    if not collections_w:
+        msg = "map() requires at least two arguments"
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    num_collections = len(collections_w)
+    none_func = space.is_w(w_func, space.w_None)
+    if none_func and num_collections == 1:
+        return space.call_function(space.w_list, collections_w[0])
+    result_w = []
+    iterators_w = [space.iter(w_seq) for w_seq in collections_w]
+    num_iterators = len(iterators_w)
+    while True:
+        cont = False
+        args_w = [space.w_None] * num_iterators
+        for i in range(len(iterators_w)):
+            try:
+                args_w[i] = space.next(iterators_w[i])
+            except OperationError, e:
+                if not e.match(space, space.w_StopIteration):
+                    raise
+            else:
+                cont = True
+        w_args = space.newtuple(args_w)
+        if cont:
+            if none_func:
+                result_w.append(w_args)
+            else:
+                w_res = space.call(w_func, w_args)
+                result_w.append(w_res)
+        else:
+            return space.newlist(result_w)
+map.unwrap_spec = [ObjSpace, W_Root, "args_w"]
 
+def sum(space, w_sequence, w_start=None):
+    if space.is_w(w_start, space.w_None):
+        w_start = space.wrap(0)
+    elif space.is_true(space.isinstance(w_start, space.w_basestring)):
+        msg = "sum() can't sum strings"
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    w_iter = space.iter(w_sequence)
+    w_last = w_start
+    while True:
+        try:
+            w_next = space.next(w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break
+        w_last = space.add(w_last, w_next)
+    return w_last
+sum.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def zip(space, sequences_w):
+    """Return a list of tuples, where the nth tuple contains every nth item of
+    each collection.
+
+    If the collections have different lengths, zip returns a list as long as the
+    shortest collection, ignoring the trailing items in the other collections.
+    """
+    if not sequences_w:
+        return space.newlist([])
+    result_w = []
+    iterators_w = [space.iter(w_seq) for w_seq in sequences_w]
+    while True:
+        try:
+            items_w = [space.next(w_it) for w_it in iterators_w]
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            return space.newlist(result_w)
+        result_w.append(space.newtuple(items_w))
+zip.unwrap_spec = [ObjSpace, "args_w"]
+
+def reduce(space, w_func, w_sequence, w_initial=NoneNotWrapped):
+    """ Apply function of two arguments cumulatively to the items of sequence,
+        from left to right, so as to reduce the sequence to a single value.
+        Optionally begin with an initial value.
+    """
+    w_iter = space.iter(w_sequence)
+    if w_initial is None:
+        try:
+            w_initial = space.next(w_iter)
+        except OperationError, e:
+            if e.match(space, space.w_StopIteration):
+                msg = "reduce() of empty sequence with no initial value"
+                raise OperationError(space.w_TypeError, space.wrap(msg))
+            raise
+    w_result = w_initial
+    while True:
+        try:
+            w_next = space.next(w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break
+        w_result = space.call_function(w_func, w_result, w_next)
+    return w_result
+reduce.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root]
+
+def filter(space, w_func, w_seq):
+    """construct a list of those elements of collection for which function
+       is True.  If function is None, then return the items in the sequence
+       which are True.
+    """
+    if space.is_true(space.isinstance(w_seq, space.w_str)):
+        return _filter_string(space, w_func, w_seq, space.w_str)
+    if space.is_true(space.isinstance(w_seq, space.w_unicode)):
+        return _filter_string(space, w_func, w_seq, space.w_unicode)
+    if space.is_true(space.isinstance(w_seq, space.w_tuple)):
+        return _filter_tuple(space, w_func, w_seq)
+    w_iter = space.iter(w_seq)
+    result_w = []
+    none_func = space.is_w(w_func, space.w_None)
+    while True:
+        try:
+            w_next = space.next(w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break
+        if none_func:
+            w_keep = w_next
+        else:
+            w_keep = space.call_function(w_func, w_next)
+        if space.is_true(w_keep):
+            result_w.append(w_next)
+    return space.newlist(result_w)
+
+def _filter_tuple(space, w_func, w_tuple):
+    none_func = space.is_w(w_func, space.w_None)
+    length = space.int_w(space.len(w_tuple))
+    result_w = []
+    for i in range(length):
+        w_item = space.getitem(w_tuple, space.wrap(i))
+        if none_func:
+            w_keep = w_item
+        else:
+            w_keep = space.call_function(w_func, w_item)
+        if space.is_true(w_keep):
+            result_w.append(w_item)
+    return space.newtuple(result_w)
+
+def _filter_string(space, w_func, w_string, w_str_type):
+    none_func = space.is_w(w_func, space.w_None)
+    if none_func and space.is_w(space.type(w_string), w_str_type):
+        return w_string
+    length = space.int_w(space.len(w_string))
+    result_w = []
+    for i in range(length):
+        w_item = space.getitem(w_string, space.wrap(i))
+        if none_func or space.is_true(space.call_function(w_func, w_item)):
+            if not space.is_true(space.isinstance(w_item, w_str_type)):
+                msg = "__getitem__ returned a non-string type"
+                raise OperationError(space.w_TypeError, space.wrap(msg))
+            result_w.append(w_item)
+    w_empty = space.call_function(w_str_type)
+    return space.call_method(w_empty, "join", space.newlist(result_w))
 
 def all(space, w_S):
     """all(iterable) -> bool
@@ -138,6 +372,110 @@
 any.unwrap_spec = [ObjSpace, W_Root]
 
 
+class W_Enumerate(Wrappable):
+
+    def __init__(self, w_iter, w_start):
+        self.w_iter = w_iter
+        self.w_index = w_start
+
+    def descr___new__(space, w_subtype, w_iterable):
+        self = space.allocate_instance(W_Enumerate, w_subtype)
+        self.__init__(space.iter(w_iterable), space.wrap(0))
+        return space.wrap(self)
+
+    def descr___iter__(self, space):
+        return space.wrap(self)
+    descr___iter__.unwrap_spec = ["self", ObjSpace]
+
+    def descr_next(self, space):
+        w_item = space.next(self.w_iter)
+        w_index = self.w_index
+        self.w_index = space.add(w_index, space.wrap(1))
+        return space.newtuple([w_index, w_item])
+    descr_next.unwrap_spec = ["self", ObjSpace]
+
+    def descr___reduce__(self, space):
+        from pypy.interpreter.mixedmodule import MixedModule
+        w_mod    = space.getbuiltinmodule('_pickle_support')
+        mod      = space.interp_w(MixedModule, w_mod)
+        w_new_inst = mod.get('enumerate_new')
+        w_info = space.newtuple([self.w_iter, self.w_index])
+        return space.newtuple([w_new_inst, w_info])
+    descr___reduce__.unwrap_spec = ["self", ObjSpace]
+
+# exported through _pickle_support
+def _make_enumerate(space, w_iter, w_index):
+    return space.wrap(W_Enumerate(w_iter, w_index))
+
+W_Enumerate.typedef = TypeDef("enumerate",
+    __new__=interp2app(W_Enumerate.descr___new__.im_func),
+    __iter__=interp2app(W_Enumerate.descr___iter__),
+    next=interp2app(W_Enumerate.descr_next),
+    __reduce__=interp2app(W_Enumerate.descr___reduce__),
+)
+
+
+def reversed(space, w_sequence):
+    """Return a iterator that yields items of sequence in reverse."""
+    w_reversed_descr = space.lookup(w_sequence, "__reversed__")
+    if w_reversed_descr is None:
+        return space.wrap(W_ReversedIterator(space, w_sequence))
+    return space.get_and_call_function(w_reversed_descr, w_sequence)
+reversed.unwrap_spec = [ObjSpace, W_Root]
+
+class W_ReversedIterator(Wrappable):
+
+    def __init__(self, space, w_sequence):
+        self.remaining = space.int_w(space.len(w_sequence)) - 1
+        self.w_sequence = w_sequence
+
+    def descr___iter__(self, space):
+        return space.wrap(self)
+    descr___iter__.unwrap_spec = ["self", ObjSpace]
+
+    def descr_next(self, space):
+        if self.remaining >= 0:
+            w_index = space.wrap(self.remaining)
+            try:
+                w_item = space.getitem(self.w_sequence, w_index)
+            except OperationError, e:
+                if not e.match(space, space.w_StopIteration):
+                    raise
+            else:
+                self.remaining -= 1
+                return w_item
+
+        # Done
+        self.remaining = -1
+        raise OperationError(space.w_StopIteration, space.w_None)
+    descr_next.unwrap_spec = ["self", ObjSpace]
+
+    def descr___reduce__(self, space):
+        from pypy.interpreter.mixedmodule import MixedModule
+        w_mod    = space.getbuiltinmodule('_pickle_support')
+        mod      = space.interp_w(MixedModule, w_mod)
+        w_new_inst = mod.get('reversed_new')
+        info_w = [self.w_sequence, space.wrap(self.remaining)]
+        w_info = space.newtuple(info_w)
+        return space.newtuple([w_new_inst, w_info])
+    descr___reduce__.unwrap_spec = ["self", ObjSpace]
+
+W_ReversedIterator.typedef = TypeDef("reversed",
+    __iter__=interp2app(W_ReversedIterator.descr___iter__),
+    next=interp2app(W_ReversedIterator.descr_next),
+    __reduce__=interp2app(W_ReversedIterator.descr___reduce__),
+)
+
+# exported through _pickle_support
+def _make_reversed(space, w_seq, w_remaining):
+    w_type = space.gettypeobject(W_ReversedIterator.typedef)
+    iterator = space.allocate_instance(W_ReversedIterator, w_type)
+    iterator.w_sequence = w_seq
+    iterator.remaining = space.int_w(w_remaining)
+    return space.wrap(iterator)
+
+
+
 class W_XRange(Wrappable):
     def __init__(self, space, start, len, step):
         self.space = space

Modified: pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py	Thu Sep 10 16:45:13 2009
@@ -22,4 +22,6 @@
         'xrangeiter_new': 'maker.xrangeiter_new',
         'builtin_code': 'maker.builtin_code',
         'builtin_function' : 'maker.builtin_function',
+        'enumerate_new': 'maker.enumerate_new',
+        'reversed_new': 'maker.reversed_new'
     }

Modified: pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py	Thu Sep 10 16:45:13 2009
@@ -100,6 +100,17 @@
 builtin_function.unwrap_spec = [ObjSpace, str]
 
 
+def enumerate_new(space, w_iter, w_index):
+    from pypy.module.__builtin__.functional import _make_enumerate
+    return _make_enumerate(space, w_iter, w_index)
+enumerate_new.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def reversed_new(space, w_seq, w_remaining):
+    from pypy.module.__builtin__.functional import _make_reversed
+    return _make_reversed(space, w_seq, w_remaining)
+reversed_new.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+
 # ___________________________________________________________________
 # Helper functions for internal use
 

Modified: pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py	Thu Sep 10 16:45:13 2009
@@ -843,7 +843,7 @@
     from pypy.rlib import rwin32
 
     eci = ExternalCompilationInfo(
-        includes = ['windows.h'],
+        includes = ['windows.h', 'wincrypt.h'],
         libraries = ['advapi32'],
         )
 

Modified: pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py	Thu Sep 10 16:45:13 2009
@@ -129,6 +129,19 @@
         assert st.st_mtime == 42.1
         assert st.st_ctime == 43
 
+    def test_stat_exception(self):
+        import sys, errno
+        try:
+            self.posix.stat("nonexistentdir/nonexistentfile")
+        except OSError, e:
+            assert e.errno == errno.ENOENT
+            # On Windows, when the parent directory does not exist,
+            # the winerror is 3 (cannot find the path specified)
+            # instead of 2 (cannot find the file specified)
+            if sys.platform == 'win32':
+                assert isinstance(e, WindowsError)
+                assert e.winerror == 3
+
     def test_pickle(self):
         import pickle, os
         st = self.posix.stat(os.curdir)

Modified: pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py	(original)
+++ pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py	Thu Sep 10 16:45:13 2009
@@ -1,6 +1,9 @@
-from pypy.jit.metainterp.policy import ManualJitPolicy
+from pypy.jit.metainterp.policy import JitPolicy
 
-class PyPyJitPolicy(ManualJitPolicy):
+class PyPyJitPolicy(JitPolicy):
+
+    def __init__(self, translator=None):
+        pass       # xxx
 
     def look_inside_function(self, func):
         mod = func.__module__ or '?'
@@ -53,6 +56,9 @@
         # string builder interface
         if mod == 'pypy.rpython.lltypesystem.rbuilder':
             return False
+        # rweakvaluedict implementation
+        if mod == 'pypy.rlib.rweakrefimpl':
+            return False
         #if (mod == 'pypy.rpython.rlist' or
         #    mod == 'pypy.rpython.lltypesystem.rdict' or
         #    mod == 'pypy.rpython.lltypesystem.rlist'):

Modified: pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py	Thu Sep 10 16:45:13 2009
@@ -5,6 +5,7 @@
 
 from pypy.rlib.objectmodel import r_dict, we_are_translated
 from pypy.rlib.jit import purefunction
+from pypy.rlib.rweakref import RWeakValueDictionary
 
 def _is_str(space, w_key):
     return space.is_w(space.type(w_key), space.w_str)
@@ -687,7 +688,6 @@
 
 class SharedStructure(object):
     def __init__(self, keys=None, length=0,
-                 other_structs=None,
                  last_key=None,
                  back_struct=None):
         if keys is None:
@@ -695,20 +695,18 @@
         self.keys = keys
         self.length = length
         self.back_struct = back_struct
-        if other_structs is None:
-            other_structs = {}
+        other_structs = RWeakValueDictionary(SharedStructure)
         self.other_structs = other_structs
         self.last_key = last_key
         if last_key is not None:
             assert back_struct is not None
-        self.propagating = False
 
     def new_structure(self, added_key):
         keys = self.keys.copy()
         keys[added_key] = len(self.keys)
         new_structure = SharedStructure(keys, self.length + 1,
-                                        {}, added_key, self)
-        self.other_structs[added_key] = new_structure
+                                        added_key, self)
+        self.other_structs.set(added_key, new_structure)
         return new_structure
 
     def lookup_position(self, key):
@@ -725,7 +723,6 @@
 class State(object):
     def __init__(self, space):
         self.empty_structure = SharedStructure()
-        self.empty_structure.propagating = True
 
 
 class SharedDictImplementation(DictImplementation):
@@ -762,13 +759,9 @@
         if i != -1:
             self.entries[i] = w_value
             return self
-        if not self.structure.propagating:
-            return self._as_rdict(as_strdict=True).setitem_str(w_key, w_value)
-        new_structure = self.structure.other_structs.get(key, None)
+        new_structure = self.structure.other_structs.get(key)
         if new_structure is None:
             new_structure = self.structure.new_structure(key)
-        else:
-            new_structure.propagating = True
         self.entries.append(w_value)
         assert self.structure.length + 1 == new_structure.length
         self.structure = new_structure

Modified: pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py	(original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py	Thu Sep 10 16:45:13 2009
@@ -948,3 +948,125 @@
         del list.a
         raises(AttributeError, "l.a")
 
+class AppTestGetattributeShortcut:
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(
+                        **{"objspace.std.getattributeshortcut": True})
+
+    def test_reset_logic(self):
+        class X(object):
+            pass
+
+        class Y(X):
+            pass
+
+        y = Y()
+        y.x = 3
+        assert y.x == 3
+
+        def ga(self, name):
+            return 'GA'
+
+        X.__getattribute__ = ga
+
+        assert y.x == 'GA'
+
+        class M(type):
+            pass
+
+        class X(object):
+            __metaclass__ = M
+
+        class Y(X):
+            pass
+
+        y = Y()
+        y.x = 3
+        assert y.x == 3
+
+        def ga(self, name):
+            return 'GA'
+
+        X.__getattribute__ = ga
+
+        assert y.x == 'GA'
+
+class TestNewShortcut:
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(
+                        **{"objspace.std.newshortcut": True})   
+
+    def test_mechanics(self):
+        space = self.space
+        w_tup = space.appexec([], """():
+    class A(object):
+        pass
+    class B(object):
+        __new__ = staticmethod(lambda t: 1)
+    class M(type):
+        pass
+    return A, B, M
+""")
+        w_A, w_B, w_M = space.unpackiterable(w_tup)
+
+        assert w_A.w_bltin_new is None
+        assert w_B.w_bltin_new is None
+        assert w_M.w_bltin_new is None                
+
+        _, w_object_newdescr = space.lookup_in_type_where(space.w_object,
+                                                          '__new__')
+        w_object___new__ = space.get(w_object_newdescr, None,
+                                     w_type=space.w_object)
+
+        w_a = space.call_function(w_A)
+        assert w_A.w_bltin_new is w_object___new__
+
+        # will shortcut
+        w_a = space.call_function(w_A)
+
+        w_b = space.call_function(w_B)
+        assert w_B.w_bltin_new is None
+
+        w_m = space.call_function(w_M, space.wrap('C'), space.newlist([]),
+                                  space.newdict())
+        assert w_M.w_bltin_new is None                                  
+
+
+class AppTestNewShortcut:
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(
+                        **{"objspace.std.newshortcut": True})
+
+    def test_reset_logic(self):
+        class X(object):
+            pass
+
+        class Y(X):
+            pass
+
+        y = Y()
+
+        assert isinstance(y, Y)
+
+
+        X.__new__ = staticmethod(lambda t: 1)
+
+        y = Y()
+
+        assert y == 1
+
+    def test_dont_explode_on_non_types(self):
+        class A:
+            __new__ = staticmethod(lambda t: 1)
+
+        class B(A, object):
+            pass
+
+        b = B()
+
+        assert b == 1
+
+        

Modified: pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py	Thu Sep 10 16:45:13 2009
@@ -50,11 +50,19 @@
     lazyloaders = {} # can be overridden by specific instances
     version_tag = None
 
-    _immutable_fields_ = ["__flags__"]
+    _immutable_fields_ = ["__flags__",
+                          'needsdel',
+                          'weakrefable',
+                          'hasdict']
 
-    uses_object_getattribute = False
-    # ^^^ for config.objspace.std.getattributeshortcut
+    # for config.objspace.std.getattributeshortcut
     # (False is a conservative default, fixed during real usage)
+    uses_object_getattribute = False
+
+    # used to cache the type __new__ function if it comes from a builtin type
+    # != 'type', in that case call__Type will also assumes the result
+    # of the __new__ is an instance of the type
+    w_bltin_new = None
 
     def __init__(w_self, space, name, bases_w, dict_w,
                  overridetypedef=None):
@@ -86,24 +94,26 @@
 
     def mutated(w_self):
         space = w_self.space
+        if (not space.config.objspace.std.withtypeversion and
+            not space.config.objspace.std.getattributeshortcut and
+            not space.config.objspace.std.newshortcut):
+            return
+
         if space.config.objspace.std.getattributeshortcut:
             w_self.uses_object_getattribute = False
             # ^^^ conservative default, fixed during real usage
-        if not space.config.objspace.std.withtypeversion:
-            return
-        # Invariant: version_tag is None if and only if
-        # 'w_self.instancetypedef.hasdict' is True, which is the case
-        # for a built-in type that provides its instances with their own
-        # __dict__.  If 'hasdict' is True for a type T then it is also
-        # True for all subtypes of T; so we don't need to look for
-        # version_tags to update in the subclasses of a type T whose
-        # version_tag is None.
-        if w_self.version_tag is not None:
+
+        if space.config.objspace.std.newshortcut:
+            w_self.w_bltin_new = None
+
+        if (space.config.objspace.std.withtypeversion
+            and w_self.version_tag is not None):
             w_self.version_tag = VersionTag()
-            subclasses_w = w_self.get_subclasses()
-            for w_subclass in subclasses_w:
-                assert isinstance(w_subclass, W_TypeObject)
-                w_subclass.mutated()
+
+        subclasses_w = w_self.get_subclasses()
+        for w_subclass in subclasses_w:
+            assert isinstance(w_subclass, W_TypeObject)
+            w_subclass.mutated()
 
     def ready(w_self):
         for w_base in w_self.bases_w:
@@ -572,10 +582,23 @@
         else:
             return space.type(w_obj)
     # invoke the __new__ of the type
-    w_newfunc = space.getattr(w_type, space.wrap('__new__'))
-    w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+    w_bltin_new = w_type.w_bltin_new
+    call_init = True
+    if w_bltin_new is not None:
+        w_newobject = space.call_obj_args(w_bltin_new, w_type, __args__)
+    else:
+        w_newtype, w_newdescr = w_type.lookup_where('__new__')
+        w_newfunc = space.get(w_newdescr, w_type)
+        if (space.config.objspace.std.newshortcut and
+            isinstance(w_newtype, W_TypeObject) and
+            not w_newtype.is_heaptype() and
+            not space.is_w(w_newtype, space.w_type)):
+            w_type.w_bltin_new = w_newfunc
+        w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+        call_init = space.is_true(space.isinstance(w_newobject, w_type))
+
     # maybe invoke the __init__ of the type
-    if space.is_true(space.isinstance(w_newobject, w_type)):
+    if call_init:
         w_descr = space.lookup(w_newobject, '__init__')
         w_result = space.get_and_call_args(w_descr, w_newobject, __args__)
         if not space.is_w(w_result, space.w_None):

Modified: pypy/branch/spine-of-frames/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/jit.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rlib/jit.py	Thu Sep 10 16:45:13 2009
@@ -1,3 +1,4 @@
+import sys
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rlib.objectmodel import CDefinedIntSymbolic
 from pypy.rlib.unroll import unrolling_iterable
@@ -82,6 +83,8 @@
 PARAMETERS = {'threshold': 1000,
               'trace_eagerness': 200,
               'hash_bits': 14,
+              'trace_limit': 10000,
+              'inlining': False,
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.keys())
 
@@ -97,7 +100,8 @@
     virtualizables = []
     
     def __init__(self, greens=None, reds=None, virtualizables=None,
-                 can_inline=None, get_printable_location=None):
+                 can_inline=None, get_printable_location=None,
+                 leave=None):
         if greens is not None:
             self.greens = greens
         if reds is not None:
@@ -112,6 +116,7 @@
         self._make_extregistryentries()
         self.get_printable_location = get_printable_location
         self.can_inline = can_inline
+        self.leave = leave
 
     def _freeze_(self):
         return True

Modified: pypy/branch/spine-of-frames/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/libffi.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rlib/libffi.py	Thu Sep 10 16:45:13 2009
@@ -311,8 +311,6 @@
                 "Procedure called with too many "
                 "arguments (%d bytes in excess) " % (result,))
 
-    
-    FormatError = rwin32.FormatError
     LoadLibrary = rwin32.LoadLibrary
 
     get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE)

Modified: pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py	Thu Sep 10 16:45:13 2009
@@ -31,6 +31,7 @@
         specialcase = "specialize:%s%s" % (self.tag, args)
         
         def specialize_decorator(func):
+            "NOT_RPYTHON"
             func._annspecialcase_ = specialcase
             return func
 

Modified: pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py	Thu Sep 10 16:45:13 2009
@@ -67,6 +67,7 @@
         return int(n)   # possibly bool->int
     if isinstance(n, objectmodel.Symbolic):
         return n        # assume Symbolics don't overflow
+    assert not isinstance(n, float)
     n = long(n)
     n &= LONG_MASK
     if n >= LONG_TEST:

Modified: pypy/branch/spine-of-frames/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/rwin32.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rlib/rwin32.py	Thu Sep 10 16:45:13 2009
@@ -55,7 +55,8 @@
             "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)")
 
         for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
-              """.split():
+                       MAX_PATH
+                    """.split():
             locals()[name] = rffi_platform.ConstantInteger(name)
 
 
@@ -112,10 +113,9 @@
         LocalFree(buf[0])
         return result
 
-    def lastWindowsError(context=None):
+    def lastWindowsError(context="Windows Error"):
         code = GetLastError()
-        message = FormatError(code)
-        return WindowsError(code, message)
+        return WindowsError(code, context)
 
     def FAILED(hr):
         return rffi.cast(HRESULT, hr) < 0
@@ -125,7 +125,7 @@
                                      DWORD)
 
     def GetModuleFileName(module):
-        size = 255 # MAX_PATH
+        size = MAX_PATH
         buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
         try:
             res = _GetModuleFileName(module, buf, size)

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py	Thu Sep 10 16:45:13 2009
@@ -370,15 +370,18 @@
         self._storage = None
 
     def __eq__(self, other):
-        if not isinstance(other, lltype._parentable):
-            return False
-        if self._storage is None or other._storage is None:
-            raise RuntimeError("pointer comparison with a freed structure")
-        if other._storage is True:
-            return False    # the other container is not ctypes-based
+        if isinstance(other, _llgcopaque):
+            addressof_other = other.intval
+        else:
+            if not isinstance(other, lltype._parentable):
+                return False
+            if self._storage is None or other._storage is None:
+                raise RuntimeError("pointer comparison with a freed structure")
+            if other._storage is True:
+                return False    # the other container is not ctypes-based
+            addressof_other = ctypes.addressof(other._storage)
         # both containers are ctypes-based, compare by address
-        return (ctypes.addressof(self._storage) ==
-                ctypes.addressof(other._storage))
+        return (ctypes.addressof(self._storage) == addressof_other)
 
     def __ne__(self, other):
         return not (self == other)
@@ -624,6 +627,7 @@
         if isinstance(container, lltype._subarray):
             topmost, index = _find_parent(container)
             container = topmost
+            T = lltype.Ptr(lltype.typeOf(container))
 
         if container._storage is None:
             raise RuntimeError("attempting to pass a freed structure to C")
@@ -1099,7 +1103,13 @@
     def __eq__(self, other):
         if isinstance(other, _llgcopaque):
             return self.intval == other.intval
-        if other.container._storage in (None, True):
+        storage = object()
+        if hasattr(other, 'container'):
+            storage = other.container._storage
+        else:
+            storage = other._storage
+
+        if storage in (None, True):
             return False
         return force_cast(lltype.Signed, other._as_ptr()) == self.intval
 

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py	Thu Sep 10 16:45:13 2009
@@ -94,6 +94,8 @@
         return addr2
 
     def setobject(self, objaddr, offset, bytes):
+        assert bytes > 0, ("llarena does not support GcStructs with no field"
+                           " or empty arrays")
         assert offset not in self.objectptrs
         self.objectptrs[offset] = objaddr.ptr
         self.objectsizes[offset] = bytes

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py	Thu Sep 10 16:45:13 2009
@@ -994,25 +994,31 @@
         return (type(self._obj0) not in (type(None), int) and
                 self._getobj(check=False)._was_freed())
 
-    def __getattr__(self, field_name): # ! can only return basic or ptr !
-        if isinstance(self._T, Struct):
-            if field_name in self._T._flds:
-                o = self._obj._getattr(field_name)
-                return self._expose(field_name, o)
+    def _lookup_adtmeth(self, member_name):
         if isinstance(self._T, ContainerType):
             try:
-                adtmeth = self._T._adtmeths[field_name]
+                adtmember = self._T._adtmeths[member_name]
             except KeyError:
                 pass
             else:
                 try:
-                    getter = adtmeth.__get__
+                    getter = adtmember.__get__
                 except AttributeError:
-                    return adtmeth
+                    return adtmember
                 else:
                     return getter(self)
-        raise AttributeError("%r instance has no field %r" % (self._T,
-                                                              field_name))
+        raise AttributeError
+
+    def __getattr__(self, field_name): # ! can only return basic or ptr !
+        if isinstance(self._T, Struct):
+            if field_name in self._T._flds:
+                o = self._obj._getattr(field_name)
+                return self._expose(field_name, o)
+        try:
+            return self._lookup_adtmeth(field_name)
+        except AttributeError:
+            raise AttributeError("%r instance has no field %r" % (self._T,
+                                                                  field_name))
 
     def __setattr__(self, field_name, val):
         if isinstance(self._T, Struct):

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py	Thu Sep 10 16:45:13 2009
@@ -507,7 +507,6 @@
 PERTURB_SHIFT = 5
 
 def ll_dict_lookup(d, key, hash):
-    DICT = lltype.typeOf(d).TO
     entries = d.entries
     mask = len(entries) - 1
     i = hash & mask
@@ -520,7 +519,7 @@
             # correct hash, maybe the key is e.g. a different pointer to
             # an equal object
             found = d.keyeq(checkingkey, key)
-            if DICT.paranoia:
+            if d.paranoia:
                 if (entries != d.entries or
                     not entries.valid(i) or entries[i].key != checkingkey):
                     # the compare did major nasty stuff to the dict: start over
@@ -555,7 +554,7 @@
                 # correct hash, maybe the key is e.g. a different pointer to
                 # an equal object
                 found = d.keyeq(checkingkey, key)
-                if DICT.paranoia:
+                if d.paranoia:
                     if (entries != d.entries or
                         not entries.valid(i) or entries[i].key != checkingkey):
                         # the compare did major nasty stuff to the dict:

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Thu Sep 10 16:45:13 2009
@@ -1091,8 +1091,38 @@
         assert ref1 == ref2
         assert ref2 == ref1
         assert not (ref1 != ref2)
-        assert not (ref2 != ref1)        
-   
+        assert not (ref2 != ref1)
+
+    def test_convert_subarray(self):
+        A = lltype.GcArray(lltype.Signed)
+        a = lltype.malloc(A, 20)
+        inside = lltype.direct_ptradd(lltype.direct_arrayitems(a), 3)
+ 
+        lltype2ctypes(inside)
+
+        start = rffi.cast(lltype.Signed, lltype.direct_arrayitems(a))
+        inside_int = rffi.cast(lltype.Signed, inside)
+
+        assert inside_int == start+rffi.sizeof(lltype.Signed)*3
+
+    def test_gcref_comparisons_through_addresses(self):
+        NODE = lltype.GcStruct('NODE')
+        n0 = lltype.malloc(NODE)
+        adr0 = llmemory.cast_ptr_to_adr(n0)
+
+        n1 = lltype.malloc(NODE)
+        i1 = rffi.cast(lltype.Signed, n1)
+        ref1 = rffi.cast(llmemory.GCREF, i1)        
+        adr1 = llmemory.cast_ptr_to_adr(ref1)
+
+        assert adr1 != adr0
+        assert adr0 != adr1
+
+        adr1_2 = llmemory.cast_ptr_to_adr(n1)
+
+        #import pdb; pdb.set_trace()
+        assert adr1_2 == adr1
+        assert adr1 == adr1_2
         
 class TestPlatform(object):
     def test_lib_on_libpaths(self):

Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py	Thu Sep 10 16:45:13 2009
@@ -528,7 +528,8 @@
 
     A = GcArray(Signed,
                 adtmeths={"h_alloc": h_alloc,
-                          "h_length": h_length})
+                          "h_length": h_length,
+                          "stuff": 12})
 
     a = A.h_alloc(10)
 
@@ -536,6 +537,9 @@
     assert len(a) == 10
 
     assert a.h_length() == 10
+    assert a._lookup_adtmeth("h_length")() == 10
+    assert a.stuff == 12
+    assert a._lookup_adtmeth("stuff") == 12
 
 def test_adt_typemethod():
     def h_newstruct(S):

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py	Thu Sep 10 16:45:13 2009
@@ -100,6 +100,7 @@
         assert not (needs_finalizer and contains_weakptr)
         if self.is_varsize(typeid):
             assert not contains_weakptr
+            assert not needs_finalizer
             itemsize = self.varsize_item_sizes(typeid)
             offset_to_length = self.varsize_offset_to_length(typeid)
             if zero or not hasattr(self, 'malloc_varsize'):
@@ -107,7 +108,7 @@
             else:
                 malloc_varsize = self.malloc_varsize
             ref = malloc_varsize(typeid, length, size, itemsize,
-                                 offset_to_length, True, needs_finalizer)
+                                 offset_to_length, True)
         else:
             if zero or not hasattr(self, 'malloc_fixedsize'):
                 malloc_fixedsize = self.malloc_fixedsize_clear

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py	Thu Sep 10 16:45:13 2009
@@ -160,8 +160,7 @@
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect,
-                             has_finalizer=False):
+                             offset_to_length, can_collect):
         # Only use the nursery if there are not too many items.
         if not raw_malloc_usage(itemsize):
             too_many_items = False
@@ -180,7 +179,7 @@
             maxlength = maxlength_for_minimal_nursery << self.nursery_scale
             too_many_items = length > maxlength
 
-        if (has_finalizer or not can_collect or
+        if (not can_collect or
             too_many_items or
             (raw_malloc_usage(size) > self.lb_young_var_basesize and
              raw_malloc_usage(size) > self.largest_young_var_basesize)):
@@ -190,7 +189,7 @@
             #     second comparison as well.
             return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
                                                     itemsize, offset_to_length,
-                                                    can_collect, has_finalizer)
+                                                    can_collect)
         # with the above checks we know now that totalsize cannot be more
         # than about half of the nursery size; in particular, the + and *
         # cannot overflow
@@ -392,6 +391,9 @@
         if self.is_in_nursery(pointer.address[0]):
             pointer.address[0] = self.copy(pointer.address[0])
 
+    # The code relies on the fact that no weakref can be an old object
+    # weakly pointing to a young object.  Indeed, weakrefs are immutable
+    # so they cannot point to an object that was created after it.
     def invalidate_young_weakrefs(self):
         # walk over the list of objects that contain weakrefs and are in the
         # nursery.  if the object it references survives then update the

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py	Thu Sep 10 16:45:13 2009
@@ -132,12 +132,11 @@
     # 'large'.
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect,
-                             has_finalizer=False):
-        if has_finalizer or not can_collect:
+                             offset_to_length, can_collect):
+        if not can_collect:
             return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
                                                     itemsize, offset_to_length,
-                                                    can_collect, has_finalizer)
+                                                    can_collect)
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
 

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py	Thu Sep 10 16:45:13 2009
@@ -131,8 +131,7 @@
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
     
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect,
-                             has_finalizer=False):
+                             offset_to_length, can_collect):
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
         try:
@@ -147,8 +146,6 @@
         self.init_gc_object(result, typeid)
         (result + size_gc_header + offset_to_length).signed[0] = length
         self.free = result + llarena.round_up_for_allocation(totalsize)
-        if has_finalizer:
-            self.objects_with_finalizers.append(result + size_gc_header)
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def obtain_free_space(self, totalsize):

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py	Thu Sep 10 16:45:13 2009
@@ -151,7 +151,7 @@
     malloc_fixedsize_clear._dont_inline_ = True
 
     def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
-                       can_collect, has_finalizer=False):
+                       can_collect):
         if can_collect:
             self.maybe_collect()
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -170,12 +170,8 @@
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
-        if has_finalizer:
-            hdr.next = self.malloced_objects_with_finalizer
-            self.malloced_objects_with_finalizer = hdr
-        else:
-            hdr.next = self.malloced_objects
-            self.malloced_objects = hdr
+        hdr.next = self.malloced_objects
+        self.malloced_objects = hdr
         self.bytes_malloced = bytes_malloced
             
         result += size_gc_header
@@ -187,8 +183,7 @@
     malloc_varsize._dont_inline_ = True
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect,
-                             has_finalizer=False):
+                             offset_to_length, can_collect):
         if can_collect:
             self.maybe_collect()
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -208,12 +203,8 @@
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
-        if has_finalizer:
-            hdr.next = self.malloced_objects_with_finalizer
-            self.malloced_objects_with_finalizer = hdr
-        else:
-            hdr.next = self.malloced_objects
-            self.malloced_objects = hdr
+        hdr.next = self.malloced_objects
+        self.malloced_objects = hdr
         self.bytes_malloced = bytes_malloced
             
         result += size_gc_header

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py	Thu Sep 10 16:45:13 2009
@@ -83,8 +83,7 @@
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect,
-                             has_finalizer=False):
+                             offset_to_length, can_collect):
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
         try:
@@ -101,8 +100,6 @@
         self.init_gc_object(result, typeid)
         (result + size_gc_header + offset_to_length).signed[0] = length
         self.free = result + llarena.round_up_for_allocation(totalsize)
-        if has_finalizer:
-            self.objects_with_finalizers.append(result + size_gc_header)
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def obtain_free_space(self, needed):

Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py	Thu Sep 10 16:45:13 2009
@@ -235,7 +235,7 @@
         self.malloc_varsize_clear_ptr = getfn(
             GCClass.malloc_varsize_clear.im_func,
             [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
-            + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
+            + [annmodel.SomeBool()], s_gcref)
         self.collect_ptr = getfn(GCClass.collect.im_func,
             [s_gc], annmodel.s_None)
         self.can_move_ptr = getfn(GCClass.can_move.im_func,
@@ -285,7 +285,7 @@
                  annmodel.SomeInteger(nonneg=True),
                  annmodel.SomeInteger(nonneg=True),
                  annmodel.SomeInteger(nonneg=True),
-                 s_True, s_False], s_gcref,
+                 s_True], s_gcref,
                 inline = True)
         else:
             self.malloc_varsize_clear_fast_ptr = None
@@ -524,30 +524,28 @@
             args = [self.c_const_gc, c_type_id, c_size, c_can_collect,
                     c_has_finalizer, rmodel.inputconst(lltype.Bool, False)]
         else:
+            assert not c_has_finalizer.value
             v_length = op.args[-1]
             c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
             c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
             if flags.get('resizable') and self.malloc_varsize_resizable_ptr:
                 assert c_can_collect.value
-                assert not c_has_finalizer.value
                 malloc_ptr = self.malloc_varsize_resizable_ptr
                 args = [self.c_const_gc, c_type_id, v_length]                
             elif flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr:
                 # we don't have tests for such cases, let's fail
                 # explicitely
                 assert c_can_collect.value
-                assert not c_has_finalizer.value
                 malloc_ptr = self.malloc_varsize_nonmovable_ptr
                 args = [self.c_const_gc, c_type_id, v_length]
             else:
                 if (self.malloc_varsize_clear_fast_ptr is not None and
-                    c_can_collect.value and not c_has_finalizer.value):
+                    c_can_collect.value):
                     malloc_ptr = self.malloc_varsize_clear_fast_ptr
                 else:
                     malloc_ptr = self.malloc_varsize_clear_ptr
                 args = [self.c_const_gc, c_type_id, v_length, c_size,
-                        c_varitemsize, c_ofstolength, c_can_collect,
-                        c_has_finalizer]
+                        c_varitemsize, c_ofstolength, c_can_collect]
         keep_current_args = flags.get('keep_current_args', False)
         livevars = self.push_roots(hop, keep_current_args=keep_current_args)
         v_result = hop.genop("direct_call", [malloc_ptr] + args,
@@ -623,12 +621,12 @@
         # used by the JIT (see pypy.jit.backend.llsupport.gc)
         op = hop.spaceop
         [v_typeid, v_length, v_size, v_itemsize,
-         v_offset_to_length, v_can_collect, v_has_finalizer] = op.args
+         v_offset_to_length, v_can_collect] = op.args
         livevars = self.push_roots(hop)
         hop.genop("direct_call",
                   [self.malloc_varsize_clear_ptr, self.c_const_gc,
                    v_typeid, v_length, v_size, v_itemsize,
-                   v_offset_to_length, v_can_collect, v_has_finalizer],
+                   v_offset_to_length, v_can_collect],
                   resultvar=op.result)
         self.pop_roots(hop, livevars)
 

Modified: pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py	Thu Sep 10 16:45:13 2009
@@ -468,24 +468,22 @@
     @registering(os.times)
     def register_os_times(self):
         if sys.platform.startswith('win'):
-            HANDLE = rffi.ULONG
-            FILETIME = rffi.CStruct('_FILETIME', ('dwLowDateTime', rffi.LONG),
-                                                 ('dwHighDateTime', rffi.LONG))
+            from pypy.rlib import rwin32
             GetCurrentProcess = self.llexternal('GetCurrentProcess', [],
-                                                HANDLE)
+                                                rwin32.HANDLE)
             GetProcessTimes = self.llexternal('GetProcessTimes',
-                                              [HANDLE,
-                                               lltype.Ptr(FILETIME),
-                                               lltype.Ptr(FILETIME),
-                                               lltype.Ptr(FILETIME),
-                                               lltype.Ptr(FILETIME)],
-                                              lltype.Bool)
+                                              [rwin32.HANDLE,
+                                               lltype.Ptr(rwin32.FILETIME),
+                                               lltype.Ptr(rwin32.FILETIME),
+                                               lltype.Ptr(rwin32.FILETIME),
+                                               lltype.Ptr(rwin32.FILETIME)],
+                                              rwin32.BOOL)
 
             def times_lltypeimpl():
-                pcreate = lltype.malloc(FILETIME, flavor='raw')
-                pexit   = lltype.malloc(FILETIME, flavor='raw')
-                pkernel = lltype.malloc(FILETIME, flavor='raw')
-                puser   = lltype.malloc(FILETIME, flavor='raw')
+                pcreate = lltype.malloc(rwin32.FILETIME, flavor='raw')
+                pexit   = lltype.malloc(rwin32.FILETIME, flavor='raw')
+                pkernel = lltype.malloc(rwin32.FILETIME, flavor='raw')
+                puser   = lltype.malloc(rwin32.FILETIME, flavor='raw')
                 hProc = GetCurrentProcess()
                 GetProcessTimes(hProc, pcreate, pexit, pkernel, puser)
                 # The fields of a FILETIME structure are the hi and lo parts
@@ -904,47 +902,29 @@
 
     @registering_if(posix, '_getfullpathname')
     def register_posix__getfullpathname(self):
+        from pypy.rlib import rwin32
         # this nt function is not exposed via os, but needed
         # to get a correct implementation of os.abspath
         # XXX why do we ignore WINAPI conventions everywhere?
-        class CConfig:
-            _compilation_info_ = ExternalCompilationInfo(
-                includes = ['Windows.h']
-            )
-            MAX_PATH = platform.ConstantInteger('MAX_PATH')
-            DWORD    = platform.SimpleType("DWORD", rffi.ULONG)
-            LPCTSTR  = platform.SimpleType("LPCTSTR", rffi.CCHARP)
-            LPTSTR   = platform.SimpleType("LPTSTR", rffi.CCHARP)
-            LPTSTRP  = platform.SimpleType("LPTSTR*", rffi.CCHARPP)
-
-        config = platform.configure(CConfig)
-        MAX_PATH = config['MAX_PATH']
-        DWORD    = config['DWORD']
-        LPCTSTR  = config['LPCTSTR']
-        LPTSTR   = config['LPTSTR']
-        LPTSTRP  = config['LPTSTRP']
+        LPSTRP = rffi.CArrayPtr(rwin32.LPSTR)
         # XXX unicode?
-        GetFullPathName = self.llexternal('GetFullPathNameA',
-                         [LPCTSTR, DWORD, LPTSTR, LPTSTRP], DWORD)
-        GetLastError = self.llexternal('GetLastError', [], DWORD)
-        ##DWORD WINAPI GetFullPathName(
-        ##  __in          LPCTSTR lpFileName,
-        ##  __in          DWORD nBufferLength,
-        ##  __out         LPTSTR lpBuffer,
-        ##  __out         LPTSTR* lpFilePart
-        ##);
+        GetFullPathName = self.llexternal(
+            'GetFullPathNameA',
+            [rwin32.LPCSTR,
+             rwin32.DWORD,
+             rwin32.LPSTR,
+             rffi.CArrayPtr(rwin32.LPSTR)],
+            rwin32.DWORD)
 
         def _getfullpathname_llimpl(lpFileName):
-            nBufferLength = MAX_PATH + 1
-            lpBuffer = lltype.malloc(LPTSTR.TO, nBufferLength, flavor='raw')
+            nBufferLength = rwin32.MAX_PATH + 1
+            lpBuffer = lltype.malloc(rwin32.LPSTR.TO, nBufferLength, flavor='raw')
             try:
                 res = GetFullPathName(
-                    lpFileName, rffi.cast(DWORD, nBufferLength),
-                    lpBuffer, lltype.nullptr(LPTSTRP.TO))
+                    lpFileName, rffi.cast(rwin32.DWORD, nBufferLength),
+                    lpBuffer, lltype.nullptr(LPSTRP.TO))
                 if res == 0:
-                    error = GetLastError()
-                    raise OSError(error, "_getfullpathname failed")
-                # XXX ntpath expects WindowsError :-(
+                    raise rwin32.lastWindowsError("_getfullpathname failed")
                 result = rffi.charp2str(lpBuffer)
                 return result
             finally:
@@ -991,14 +971,13 @@
     def register_os_listdir(self):
         # we need a different approach on Windows and on Posix
         if sys.platform.startswith('win'):
+            from pypy.rlib import rwin32
             class CConfig:
                 _compilation_info_ = ExternalCompilationInfo(
                     includes = ['windows.h']
                 )
                 WIN32_FIND_DATA = platform.Struct('struct _WIN32_FIND_DATAA',
                     [('cFileName', lltype.FixedSizeArray(rffi.CHAR, 1))])
-                INVALID_HANDLE_VALUE = platform.ConstantInteger(
-                    'INVALID_HANDLE_VALUE')
                 ERROR_FILE_NOT_FOUND = platform.ConstantInteger(
                     'ERROR_FILE_NOT_FOUND')
                 ERROR_NO_MORE_FILES = platform.ConstantInteger(
@@ -1006,23 +985,19 @@
 
             config = platform.configure(CConfig)
             WIN32_FIND_DATA      = config['WIN32_FIND_DATA']
-            INVALID_HANDLE_VALUE = config['INVALID_HANDLE_VALUE']
             ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND']
             ERROR_NO_MORE_FILES  = config['ERROR_NO_MORE_FILES']
             LPWIN32_FIND_DATA    = lltype.Ptr(WIN32_FIND_DATA)
-            HANDLE               = rffi.ULONG
-            #MAX_PATH = WIN32_FIND_DATA.c_cFileName.length
 
-            GetLastError = self.llexternal('GetLastError', [], lltype.Signed)
             FindFirstFile = self.llexternal('FindFirstFile',
-                                            [rffi.CCHARP, LPWIN32_FIND_DATA],
-                                            HANDLE)
+                                            [rwin32.LPCSTR, LPWIN32_FIND_DATA],
+                                            rwin32.HANDLE)
             FindNextFile = self.llexternal('FindNextFile',
-                                           [HANDLE, LPWIN32_FIND_DATA],
-                                           rffi.INT)
+                                           [rwin32.HANDLE, LPWIN32_FIND_DATA],
+                                           rwin32.BOOL)
             FindClose = self.llexternal('FindClose',
-                                        [HANDLE],
-                                        rffi.INT)
+                                        [rwin32.HANDLE],
+                                        rwin32.BOOL)
 
             def os_listdir_llimpl(path):
                 if path and path[-1] not in ('/', '\\', ':'):
@@ -1032,13 +1007,12 @@
                 try:
                     result = []
                     hFindFile = FindFirstFile(path, filedata)
-                    if hFindFile == INVALID_HANDLE_VALUE:
-                        error = GetLastError()
+                    if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+                        error = rwin32.GetLastError()
                         if error == ERROR_FILE_NOT_FOUND:
                             return result
                         else:
-                            # XXX guess error code :-(
-                            raise OSError(errno.ENOENT, "FindFirstFile failed")
+                            raise WindowsError(error,  "FindFirstFile failed")
                     while True:
                         name = rffi.charp2str(rffi.cast(rffi.CCHARP,
                                                         filedata.c_cFileName))
@@ -1048,13 +1022,12 @@
                             break
                     # FindNextFile sets error to ERROR_NO_MORE_FILES if
                     # it got to the end of the directory
-                    error = GetLastError()
+                    error = rwin32.GetLastError()
                     FindClose(hFindFile)
                     if error == ERROR_NO_MORE_FILES:
                         return result
                     else:
-                        # XXX guess error code :-(
-                        raise OSError(errno.EIO, "FindNextFile failed")
+                        raise WindowsError(error,  "FindNextFile failed")
                 finally:
                     lltype.free(filedata, flavor='raw')
 
@@ -1107,28 +1080,31 @@
     def register_os_pipe(self):
         # we need a different approach on Windows and on Posix
         if sys.platform.startswith('win'):
-            HANDLE = rffi.ULONG
-            HANDLEP = lltype.Ptr(lltype.FixedSizeArray(HANDLE, 1))
-            CreatePipe = self.llexternal('CreatePipe', [HANDLEP,
-                                                        HANDLEP,
+            from pypy.rlib import rwin32
+            CreatePipe = self.llexternal('CreatePipe', [rwin32.LPHANDLE,
+                                                        rwin32.LPHANDLE,
                                                         rffi.VOIDP,
-                                                        rffi.ULONG],
-                                         rffi.INT)
+                                                        rwin32.DWORD],
+                                         rwin32.BOOL)
             _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.ULONG,
                                                                   rffi.INT],
                                               rffi.INT)
             null = lltype.nullptr(rffi.VOIDP.TO)
 
             def os_pipe_llimpl():
-                pread  = lltype.malloc(HANDLEP.TO, flavor='raw')
-                pwrite = lltype.malloc(HANDLEP.TO, flavor='raw')
+                pread  = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
+                pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
                 ok = CreatePipe(pread, pwrite, null, 0)
+                if ok:
+                    error = 0
+                else:
+                    error = rwin32.GetLastError()
                 hread = pread[0]
                 hwrite = pwrite[0]
                 lltype.free(pwrite, flavor='raw')
                 lltype.free(pread, flavor='raw')
-                if not ok:    # XXX guess the error, can't use GetLastError()
-                    raise OSError(errno.EMFILE, "os_pipe failed")
+                if error:
+                    raise WindowsError(error, "os_pipe failed")
                 fdread = _open_osfhandle(hread, 0)
                 fdwrite = _open_osfhandle(hwrite, 1)
                 return (fdread, fdwrite)

Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py	Thu Sep 10 16:45:13 2009
@@ -258,6 +258,14 @@
             graphs.update(SUBTYPE._lookup_graphs(meth_name))
         return graphs
 
+    def _get_fields_with_different_default(self):
+        fields = []
+        example = self._example()
+        for field in self._allfields().iteritems():
+            name, (T, value) = field
+            if T._defl() != value:
+                fields.append(field)
+        return fields
 
 
 class SpecializableType(OOType):

Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py	Thu Sep 10 16:45:13 2009
@@ -21,9 +21,7 @@
     if robj1 == none_frozen_pbc_repr:
         return hop.inputconst(ootype.Bool, True)
     v1 = hop.inputarg(robj1, pos)
-    v2 = hop.genop('oononnull', [v1], resulttype=ootype.Bool)
-    v3 = hop.genop('bool_not', [v2], resulttype=ootype.Bool)
-    return v3
+    return hop.genop('ooisnull', [v1], resulttype=ootype.Bool)
 
 
 class FunctionsPBCRepr(AbstractFunctionsPBCRepr):

Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py	Thu Sep 10 16:45:13 2009
@@ -654,3 +654,11 @@
     SM = StaticMethod([], Void)
     sm = SM._defl()
     assert not bool(sm)
+
+def test_get_fields_with_different_default():
+    A = Instance("A", ROOT, {"a": (Signed, 3),
+                             "b": (Signed, 0),
+                             "c": (ROOT, ROOT._defl())
+                             })
+    fields = A._get_fields_with_different_default()
+    assert fields == [("a", (Signed, 3))]

Modified: pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py	Thu Sep 10 16:45:13 2009
@@ -268,6 +268,16 @@
         v_errno = hop.inputarg(lltype.Signed, arg=1)
         r_self.setfield(v_self, 'errno', v_errno, hop.llops)
 
+def rtype_WindowsError__init__(hop):
+    if hop.nb_args == 2:
+        raise TyperError("WindowsError() should not be called with "
+                         "a single argument")
+    if hop.nb_args >= 3:
+        v_self = hop.args_v[0]
+        r_self = hop.args_r[0]
+        v_error = hop.inputarg(lltype.Signed, arg=1)
+        r_self.setfield(v_self, 'winerror', v_error, hop.llops)
+
 def rtype_we_are_translated(hop):
     hop.exception_cannot_occur()
     return hop.inputconst(lltype.Bool, True)
@@ -318,6 +328,15 @@
 BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = (
     rtype_OSError__init__)
 
+try:
+    WindowsError
+except NameError:
+    pass
+else:
+    BUILTIN_TYPER[
+        getattr(WindowsError.__init__, 'im_func', WindowsError.__init__)] = (
+        rtype_WindowsError__init__)
+
 BUILTIN_TYPER[object.__init__] = rtype_object__init__
 # annotation of low-level types
 

Modified: pypy/branch/spine-of-frames/pypy/rpython/rint.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rint.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rint.py	Thu Sep 10 16:45:13 2009
@@ -385,6 +385,7 @@
 
     def rtype_float(_, hop):
         vlist = hop.inputargs(Float)
+        hop.exception_cannot_occur()
         return vlist[0]
 
     # version picked by specialisation based on which

Modified: pypy/branch/spine-of-frames/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rpbc.py	Thu Sep 10 16:45:13 2009
@@ -834,7 +834,15 @@
                                  "classes with no common base: %r" % (mdescs,))
 
         self.methodname = methodname
-        self.classdef = classdef.locate_attribute(methodname)
+        # for ootype, the right thing to do is to always keep the most precise
+        # type of the instance, while for lltype we want to cast it to the
+        # type where the method is actually defined. See also
+        # test_rclass.test_method_specialized_with_subclass and
+        # rtyper.attach_methods_to_subclasses
+        if self.rtyper.type_system.name == 'ootypesystem':
+            self.classdef = classdef
+        else:
+            self.classdef = classdef.locate_attribute(methodname)
         # the low-level representation is just the bound 'self' argument.
         self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags)
         self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef)

Modified: pypy/branch/spine-of-frames/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rtyper.py	Thu Sep 10 16:45:13 2009
@@ -198,7 +198,9 @@
         if self.exceptiondata is not None:
             self.exceptiondata.make_helpers(self)
             self.specialize_more_blocks()   # for the helpers just made
-
+        if self.type_system.name == 'ootypesystem':
+            self.attach_methods_to_subclasses()
+        
         #
         from pypy.annotation import listdef
         ldef = listdef.ListDef(None, annmodel.SomeString())
@@ -268,6 +270,40 @@
         if annmixlevel is not None:
             annmixlevel.finish()
 
+    def attach_methods_to_subclasses(self):
+        # in ootype, it might happen that a method is defined in the
+        # superclass but the annotator discovers that it's always called
+        # through instances of a subclass (e.g. because of specialization, see
+        # test_rclass.test_method_specialized_with_subclass).  In that cases,
+        # we copy the method also in the ootype.Instance of the subclass, so
+        # that the type of v_self coincides with the type returned by
+        # _lookup().
+        assert self.type_system.name == 'ootypesystem'
+        def allclasses(TYPE, seen):
+            '''Yield TYPE and all its subclasses'''
+            if TYPE in seen:
+                return
+            seen.add(TYPE)
+            yield TYPE
+            for SUB in TYPE._subclasses:
+                for T in allclasses(SUB, seen):
+                    yield T
+
+        for TYPE in allclasses(ootype.ROOT, set()):
+            for methname, meth in TYPE._methods.iteritems():
+                try:
+                    graph = meth.graph
+                except AttributeError:
+                    continue
+                SELF = graph.getargs()[0].concretetype
+                if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
+                    # the annotator found that this method has a more precise
+                    # type. Attach it to the proper subclass, so that the type
+                    # of 'self' coincides with the type returned by _lookup(),
+                    # else we might have type errors
+                    if methname not in SELF._methods:
+                        ootype.addMethods(SELF, {methname: meth})
+
     def dump_typererrors(self, num=None, minimize=True, to_log=False): 
         c = 0
         bc = 0

Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py	Thu Sep 10 16:45:13 2009
@@ -389,6 +389,26 @@
             lst.append(6)
         self.annotate(llf, [])
 
+    def test_adtmeths(self):
+        def h_length(s):
+            return s.foo
+        S = GcStruct("S", ('foo', Signed),
+                     adtmeths={"h_length": h_length,
+                               "stuff": 12})
+        def llf():
+            s = malloc(S)
+            s.foo = 321
+            return s.h_length()
+        s = self.annotate(llf, [])
+        assert s.knowntype == int and not s.is_constant()
+
+        def llf():
+            s = malloc(S)
+            return s.stuff
+        s = self.annotate(llf, [])
+        assert s.is_constant() and s.const == 12
+
+
 def test_pseudohighlevelcallable():
     t = TranslationContext()
     t.buildannotator()

Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py	Thu Sep 10 16:45:13 2009
@@ -266,6 +266,25 @@
         res = self.interpret(f, [])
         assert res == 246
 
+    def test_method_specialized_with_subclass(self):
+        class A:
+            def meth(self, n):
+                return -1
+            meth._annspecialcase_ = 'specialize:arg(1)'
+
+        class B(A):
+            pass
+        
+        def f():
+            a = A()
+            b = B()
+            a.meth(1) # the self of this variant is annotated with A
+            b.meth(2) # the self of this variant is annotated with B
+            return 42
+        
+        res = self.interpret(f, [])
+        assert res == 42
+
     def test_issubclass_type(self):
         class Abstract:
             pass

Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py	(original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py	Thu Sep 10 16:45:13 2009
@@ -327,6 +327,16 @@
         res = self.interpret(f, [sys.maxint])
         assert res == 0
 
+    def test_cast_to_float_exc_check(self):
+        def f(x):
+            try:
+                return float(x)
+            except ValueError:
+                return 3.0
+
+        res = self.interpret(f, [3])
+        assert res == 3
+
 class TestLLtype(BaseTestRint, LLRtypeMixin):
     pass
 

Modified: pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py	Thu Sep 10 16:45:13 2009
@@ -7,7 +7,9 @@
 from pypy import conftest
 
 if sys.platform == 'win32':
-    py.test.skip("No asmgcc on Windows")
+    if not ('mingw' in os.popen('gcc --version').read() and
+            'GNU' in os.popen('make --version').read()):
+        py.test.skip("mingw32 and MSYS are required for asmgcc on Windows")
 
 class AbstractTestAsmGCRoot:
     # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
@@ -30,6 +32,8 @@
         config = get_pypy_config(translating=True)
         config.translation.gc = self.gcpolicy
         config.translation.gcrootfinder = "asmgcc"
+        if sys.platform == 'win32':
+            config.translation.cc = 'mingw32'
         t = TranslationContext(config=config)
         self.t = t
         a = t.buildannotator()
@@ -48,7 +52,7 @@
         def run():
             lines = []
             print >> sys.stderr, 'RUN: starting', exe_name
-            g = os.popen("'%s'" % (exe_name,), 'r')
+            g = os.popen('"%s"' % (exe_name,), 'r')
             for line in g:
                 print >> sys.stderr, 'RUN:', line.rstrip()
                 lines.append(line)

Modified: pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py	Thu Sep 10 16:45:13 2009
@@ -23,15 +23,16 @@
 r_functionstart_darwin = re.compile(r"_(\w+):\s*$")
 
 # inside functions
-r_label         = re.compile(r"([.]?\w+)[:]\s*$")
+LABEL           = r'([.]?[\w$@]+)'
+r_label         = re.compile(LABEL+"[:]\s*$")
 r_globl         = re.compile(r"\t[.]globl\t(\w+)\s*$")
 r_insn          = re.compile(r"\t([a-z]\w*)\s")
-r_jump          = re.compile(r"\tj\w+\s+([.]?[\w$]+)\s*$")
+r_jump          = re.compile(r"\tj\w+\s+"+LABEL+"\s*$")
 OPERAND         =           r'(?:[-\w$%+.:@"]+(?:[(][\w%,]+[)])?|[(][\w%,]+[)])'
 r_unaryinsn     = re.compile(r"\t[a-z]\w*\s+("+OPERAND+")\s*$")
 r_unaryinsn_star= re.compile(r"\t[a-z]\w*\s+([*]"+OPERAND+")\s*$")
-r_jmp_switch    = re.compile(r"\tjmp\t[*]([.]?\w+)[(]")
-r_jmptable_item = re.compile(r"\t.long\t([.]?\w+)\s*$")
+r_jmp_switch    = re.compile(r"\tjmp\t[*]"+LABEL+"[(]")
+r_jmptable_item = re.compile(r"\t.long\t"+LABEL+"\s*$")
 r_jmptable_end  = re.compile(r"\t.text|\t.section\s+.text")
 r_binaryinsn    = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$")
 LOCALVAR        = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]"
@@ -75,23 +76,22 @@
         shapelines = []
         shapeofs = 0
         def _globalname(name):
-            if self.format == 'darwin':
+            if self.format in ('darwin', 'mingw32'):
                 return '_' + name
             return name
         def _globl(name):
             print >> output, "\t.globl %s" % _globalname(name)
         def _label(name):
             print >> output, "%s:" % _globalname(name)
-        def _variant(elf, darwin):
-            if self.format == 'darwin':
-                txt = darwin
-            else:
-                txt = elf
+        def _variant(**kwargs):
+            txt = kwargs[self.format]
             print >> output, "\t%s" % txt
-        
+
         print >> output, "\t.text"
         _globl('pypy_asm_stackwalk')
-        _variant('.type pypy_asm_stackwalk, @function', '')
+        _variant(elf='.type pypy_asm_stackwalk, @function',
+                 darwin='',
+                 mingw32='')
         _label('pypy_asm_stackwalk')
         print >> output, """\
             /* See description in asmgcroot.py */
@@ -114,7 +114,9 @@
             popl   %eax
             ret
 """
-        _variant('.size pypy_asm_stackwalk, .-pypy_asm_stackwalk', '')
+        _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
+                 darwin='',
+                 mingw32='')
         print >> output, '\t.data'
         print >> output, '\t.align\t4'
         _globl('__gcmapstart')
@@ -135,7 +137,9 @@
             print >> output, '\t.long\t%d' % (n,)
         _globl('__gcmapend')
         _label('__gcmapend')
-        _variant('.section\t.rodata', '.const')
+        _variant(elf='.section\t.rodata',
+                 darwin='.const',
+                 mingw32='')
         _globl('__gccallshapes')
         _label('__gccallshapes')
         output.writelines(shapelines)
@@ -188,8 +192,10 @@
         if functionlines:
             yield in_function, functionlines
 
+    _find_functions_mingw32 = _find_functions_darwin
+
     def process(self, iterlines, newfile, entrypoint='main', filename='?'):
-        if self.format == 'darwin':
+        if self.format in ('darwin', 'mingw32'):
             entrypoint = '_' + entrypoint
         for in_function, lines in self.find_functions(iterlines):
             if in_function:
@@ -232,6 +238,9 @@
         elif format == 'darwin':
             match = r_functionstart_darwin.match(lines[0])
             funcname = '_'+match.group(1)
+        elif format == 'mingw32':
+            match = r_functionstart_darwin.match(lines[0])
+            funcname = '_'+match.group(1)
         else:
             assert False, "unknown format: %s" % format
  
@@ -738,8 +747,15 @@
                 if lineoffset >= 0:
                     assert  lineoffset in (1,2)
                     return [InsnStackAdjust(-4)]
-        return [InsnCall(self.currentlineno),
-                InsnSetLocal('%eax')]      # the result is there
+        insns = [InsnCall(self.currentlineno),
+                 InsnSetLocal('%eax')]      # the result is there
+        if sys.platform == 'win32':
+            # handle __stdcall calling convention:
+            # Stack cleanup is performed by the called function,
+            # Function name is decorated with "@N" where N is the stack size
+            if match and '@' in target:
+                insns.append(InsnStackAdjust(int(target.split('@')[1])))
+        return insns
 
 
 class UnrecognizedOperation(Exception):
@@ -1108,6 +1124,8 @@
             break
     if sys.platform == 'darwin':
         format = 'darwin'
+    elif sys.platform == 'win32':
+        format = 'mingw32'
     else:
         format = 'elf'
     tracker = GcRootTracker(verbose=verbose, shuffle=shuffle, format=format)

Modified: pypy/branch/spine-of-frames/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/genc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/genc.py	Thu Sep 10 16:45:13 2009
@@ -492,8 +492,14 @@
             mk.definition('GCMAPFILES', gcmapfiles)
             mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s')
             mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
-            mk.rule('%.lbl.s %.gcmap', '%.s', '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
-            mk.rule('gcmaptable.s', '$(GCMAPFILES)', '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
+            if sys.platform == 'win32':
+                python = sys.executable.replace('\\', '/') + ' '
+            else:
+                python = ""
+            mk.rule('%.lbl.s %.gcmap', '%.s',
+                    python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
+            mk.rule('gcmaptable.s', '$(GCMAPFILES)',
+                    python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
 
         mk.write()
         #self.translator.platform,
@@ -785,7 +791,10 @@
     for key, value in defines.items():
         print >> fi, '#define %s %s' % (key, value)
 
-    print >> fi, '#define Py_BUILD_CORE  /* for Windows: avoid pulling libs in */'
+    if sys.platform == 'win32':
+        print >> fi, '#define Py_BUILD_CORE /* avoid pulling python libs in */'
+        print >> fi, '#define WIN32_LEAN_AND_MEAN /* winsock/winsock2 mess */'
+
     print >> fi, '#include "pyconfig.h"'
 
     eci.write_c_header(fi)
@@ -838,6 +847,9 @@
     for key, value in defines.items():
         print >> fi, '#define %s %s' % (key, value)
 
+    if sys.platform == 'win32':
+        print >> fi, '#define WIN32_LEAN_AND_MEAN /* winsock/winsock2 mess */'
+
     print >> fi, '#include "pyconfig.h"'
 
     eci.write_c_header(fi)

Modified: pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h	Thu Sep 10 16:45:13 2009
@@ -4,12 +4,6 @@
 /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch at iso.ru */
 /* Eliminated some memory leaks, gsw at agere.com */
 
-/* Windows.h includes winsock.h, but the socket module needs */ 
-/* winsock2.h. So I include it before. Ugly. */
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
 #include <windows.h>
 #include <limits.h>
 #include <process.h>
@@ -61,7 +55,7 @@
   return GetCurrentThreadId();
 }
 
-static int
+static void
 bootstrap(void *call)
 {
 	callobj *obj = (callobj*)call;
@@ -71,7 +65,6 @@
 	obj->id = RPyThreadGetIdent();
 	ReleaseSemaphore(obj->done, 1, NULL);
 	func();
-	return 0;
 }
 
 long RPyThreadStart(void (*func)(void))
@@ -130,69 +123,14 @@
 /************************************************************/
 
 
-typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
-
-/* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */
-static PVOID WINAPI interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand)
-{
-	static LONG spinlock = 0 ;
-	PVOID result ;
-	DWORD dwSleep = 0;
-
-	/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
-	while(InterlockedExchange(&spinlock, 1))
-	{
-		// Using Sleep(0) can cause a priority inversion.
-		// Sleep(0) only yields the processor if there's
-		// another thread of the same priority that's
-		// ready to run.  If a high-priority thread is
-		// trying to acquire the lock, which is held by
-		// a low-priority thread, then the low-priority
-		// thread may never get scheduled and hence never
-		// free the lock.  NT attempts to avoid priority
-		// inversions by temporarily boosting the priority
-		// of low-priority runnable threads, but the problem
-		// can still occur if there's a medium-priority
-		// thread that's always runnable.  If Sleep(1) is used,
-		// then the thread unconditionally yields the CPU.  We
-		// only do this for the second and subsequent even
-		// iterations, since a millisecond is a long time to wait
-		// if the thread can be scheduled in again sooner
-		// (~100,000 instructions).
-		// Avoid priority inversion: 0, 1, 0, 1,...
-		Sleep(dwSleep);
-		dwSleep = !dwSleep;
-	}
-	result = *dest ;
-	if (result == comperand)
-		*dest = exc ;
-	/* Release spinlock */
-	spinlock = 0 ;
-	return result ;
-} ;
-
-static interlocked_cmp_xchg_t *ixchg ;
 BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex)
 {
-	if (!ixchg)
-	{
-		/* Sorely, Win95 has no InterlockedCompareExchange API (Win98 has), so we have to use emulation */
-		HANDLE kernel = GetModuleHandle("kernel32.dll") ;
-		if (!kernel || (ixchg = (interlocked_cmp_xchg_t *)GetProcAddress(kernel, "InterlockedCompareExchange")) == NULL)
-			ixchg = interlocked_cmp_xchg ;
-	}
-
 	mutex->owned = -1 ;  /* No threads have entered NonRecursiveMutex */
 	mutex->thread_id = 0 ;
 	mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
 	return mutex->hevent != NULL ;	/* TRUE if the mutex is created */
 }
 
-#ifdef InterlockedCompareExchange
-#undef InterlockedCompareExchange
-#endif
-#define InterlockedCompareExchange(dest,exchange,comperand) (ixchg((dest), (exchange), (comperand)))
-
 VOID DeleteNonRecursiveMutex(PNRMUTEX mutex)
 {
 	/* No in-use check */
@@ -208,7 +146,7 @@
 	/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
 	if (!wait)
 	{
-		if (InterlockedCompareExchange((PVOID *)&mutex->owned, (PVOID)0, (PVOID)-1) != (PVOID)-1)
+		if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
 			return WAIT_TIMEOUT ;
 		ret = WAIT_OBJECT_0 ;
 	}

Modified: pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py	Thu Sep 10 16:45:13 2009
@@ -173,6 +173,19 @@
         if has_blocks:
             assert res[4] == os.stat(filename).st_blocks
 
+def test_os_stat_raises_winerror():
+    if sys.platform != 'win32':
+        py.test.skip("no WindowsError on this platform")
+    def call_stat():
+        try:
+            os.stat("nonexistentdir/nonexistentfile")
+        except WindowsError, e:
+            return e.winerror
+    f = compile(call_stat, [])
+    res = f()
+    expected = call_stat()
+    assert res == expected
+
 def test_os_fstat():
     if os.environ.get('PYPY_CC', '').startswith('tcc'):
         py.test.skip("segfault with tcc :-(")

Modified: pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py	Thu Sep 10 16:45:13 2009
@@ -114,9 +114,8 @@
     'ullong_is_true':            [PushAllArgs, 'ldc.i8 0', 'cgt.un'],
     'ullong_invert':             'not',
 
-    # XXX: why nop nop nop?
-    'ooisnull':                 [PushAllArgs, 'nop', 'nop', 'nop', 'ldnull', 'ceq'],
-    'oononnull':                [PushAllArgs, 'nop', 'nop', 'nop', 'nop', 'ldnull', 'ceq']+Not,
+    'ooisnull':                 [PushAllArgs, 'ldnull', 'ceq'],
+    'oononnull':                [PushAllArgs, 'ldnull', 'ceq']+Not,
 
     # when casting from bool we want that every truth value is casted
     # to 1: we can't simply DoNothing, because the CLI stack could

Modified: pypy/branch/spine-of-frames/pypy/translator/driver.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/driver.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/driver.py	Thu Sep 10 16:45:13 2009
@@ -362,7 +362,7 @@
         from pypy.jit.metainterp.warmspot import apply_jit
         apply_jit(self.translator, policy=self.jitpolicy,
                   debug_level=self.config.translation.jit_debug,
-                  backend_name=self.config.translation.jit_backend)
+                  backend_name=self.config.translation.jit_backend, inline=True)
         #
         self.log.info("the JIT compiler was generated")
     #

Modified: pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py	Thu Sep 10 16:45:13 2009
@@ -1,6 +1,6 @@
 from pypy.translator.jvm.typesystem import \
      IFLT, IFLE, IFEQ, IFNE, IFGT, IFGE, \
-     IFNONNULL, IF_ACMPEQ, GOTO, ICONST, \
+     IFNONNULL, IFNULL, IF_ACMPEQ, GOTO, ICONST, \
      DCONST_0, DCMPG, LCONST_0, LCMP, \
      IF_ICMPLT, IF_ICMPLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPGT, IF_ICMPGE, \
      PYPYUINTCMP, PYPYULONGCMP
@@ -52,6 +52,7 @@
 
     # Double operand entries:
     'oononnull': [IFNONNULL],
+    'ooisnull': [IFNULL],
     'oois': [IF_ACMPEQ],
 
     'unichar_eq': [IF_ICMPEQ],

Modified: pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py	Thu Sep 10 16:45:13 2009
@@ -110,9 +110,9 @@
             errorfile = outname.new(ext='errors')
             errorfile.write(stderr)
             stderrlines = stderr.splitlines()
-            for line in stderrlines[:20]:
+            for line in stderrlines[:50]:
                 log.ERROR(line)
-            if len(stderrlines) > 20:
+            if len(stderrlines) > 50:
                 log.ERROR('...')
             raise CompilationError(stdout, stderr)
 

Modified: pypy/branch/spine-of-frames/pypy/translator/platform/posix.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/posix.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/posix.py	Thu Sep 10 16:45:13 2009
@@ -121,6 +121,7 @@
     def write(self, f):
         def write_list(prefix, lst):
             for i, fn in enumerate(lst):
+                fn = fn.replace('\\', '\\\\')
                 print >> f, prefix, fn,
                 if i < len(lst)-1:
                     print >> f, '\\'
@@ -129,7 +130,7 @@
                 prefix = ' ' * len(prefix)
         name, value = self.name, self.value
         if isinstance(value, str):
-            f.write('%s = %s\n' % (name, value))
+            f.write('%s = %s\n' % (name, value.replace('\\', '\\\\')))
         else:
             write_list('%s =' % (name,), value)
         if value:
@@ -171,7 +172,8 @@
         if fpath.dirpath() == self.makefile_dir:
             return fpath.basename
         elif fpath.dirpath().dirpath() == self.makefile_dir.dirpath():
-            return '../' + fpath.relto(self.makefile_dir.dirpath())
+            path = '../' + fpath.relto(self.makefile_dir.dirpath())
+            return path.replace('\\', '/')
         else:
             return str(fpath)
 

Modified: pypy/branch/spine-of-frames/pypy/translator/platform/windows.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/windows.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/windows.py	Thu Sep 10 16:45:13 2009
@@ -281,4 +281,7 @@
     def library_dirs_for_libffi(self):
         return []
 
-
+    def _handle_error(self, returncode, stderr, stdout, outname):
+        # Mingw tools write compilation errors to stdout
+        super(MingwPlatform, self)._handle_error(
+            returncode, stderr + stdout, '', outname)

Modified: pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py	(original)
+++ pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py	Thu Sep 10 16:45:13 2009
@@ -249,6 +249,8 @@
             f = filename.open("w")
             if being_main:
                 f.write("#define PYPY_NOT_MAIN_FILE\n")
+            if sys.platform == 'win32':
+                f.write("#define WIN32_LEAN_AND_MEAN\n")
             self.write_c_header(f)
             source = str(source)
             f.write(source)



More information about the Pypy-commit mailing list