[pypy-svn] r77830 - in pypy/branch/32ptr-on-64bit/pypy: annotation annotation/test config doc doc/config interpreter interpreter/astcompiler/test interpreter/pyparser jit/backend/test jit/backend/x86 jit/backend/x86/test jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/optimizeopt jit/metainterp/test jit/tl/spli module/__builtin__ module/__builtin__/test module/_weakref module/cpyext module/gc module/pypyjit/test module/signal module/sys objspace/std objspace/std/test rlib rlib/test rpython rpython/lltypesystem rpython/module rpython/test translator/c/gcc translator/c/gcc/test/elf translator/c/src translator/goal translator/jvm/test translator/oosupport/test_template

arigo at codespeak.net arigo at codespeak.net
Tue Oct 12 14:43:05 CEST 2010


Author: arigo
Date: Tue Oct 12 14:42:59 2010
New Revision: 77830

Added:
   pypy/branch/32ptr-on-64bit/pypy/doc/config/objspace.std.withmapdict.txt
      - copied unchanged from r77829, pypy/trunk/pypy/doc/config/objspace.std.withmapdict.txt
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/autopath.py
      - copied unchanged from r77829, pypy/trunk/pypy/interpreter/pyparser/autopath.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/genpytokenize.py
      - copied unchanged from r77829, pypy/trunk/pypy/interpreter/pyparser/genpytokenize.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/pylexer.py
      - copied unchanged from r77829, pypy/trunk/pypy/interpreter/pyparser/pylexer.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/mapdict.py
      - copied unchanged from r77829, pypy/trunk/pypy/objspace/std/mapdict.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/strbufobject.py
      - copied unchanged from r77829, pypy/trunk/pypy/objspace/std/strbufobject.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_mapdict.py
      - copied unchanged from r77829, pypy/trunk/pypy/objspace/std/test/test_mapdict.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_strbufobject.py
      - copied unchanged from r77829, pypy/trunk/pypy/objspace/std/test/test_strbufobject.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/rerased.py
      - copied unchanged from r77829, pypy/trunk/pypy/rlib/rerased.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rerased.py
      - copied unchanged from r77829, pypy/trunk/pypy/rlib/test/test_rerased.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track10.s
      - copied unchanged from r77829, pypy/trunk/pypy/translator/c/gcc/test/elf/track10.s
   pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track11.s
      - copied unchanged from r77829, pypy/trunk/pypy/translator/c/gcc/test/elf/track11.s
Removed:
   pypy/branch/32ptr-on-64bit/pypy/rpython/rspecialcase.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rspecialcase.py
Modified:
   pypy/branch/32ptr-on-64bit/pypy/annotation/policy.py
   pypy/branch/32ptr-on-64bit/pypy/annotation/test/test_annrpython.py
   pypy/branch/32ptr-on-64bit/pypy/config/pypyoption.py
   pypy/branch/32ptr-on-64bit/pypy/doc/docindex.txt
   pypy/branch/32ptr-on-64bit/pypy/interpreter/astcompiler/test/test_compiler.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/baseobjspace.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pycode.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyframe.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyopcode.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/pytokenize.py
   pypy/branch/32ptr-on-64bit/pypy/interpreter/typedef.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/runner_test.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/test_ll_random.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/assembler.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/regalloc.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_runner.py
   pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_string.py
   pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/effectinfo.py
   pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/jtransform.py
   pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/test/test_jtransform.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/history.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimize_nopspec.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/intbounds.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/rewrite.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/string.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/resume.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/simple_optimize.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/oparser.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizefindnode.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_resume.py
   pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_string.py
   pypy/branch/32ptr-on-64bit/pypy/jit/tl/spli/interpreter.py
   pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/interp_classobj.py
   pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/test/test_classobj.py
   pypy/branch/32ptr-on-64bit/pypy/module/_weakref/interp__weakref.py
   pypy/branch/32ptr-on-64bit/pypy/module/cpyext/classobject.py
   pypy/branch/32ptr-on-64bit/pypy/module/gc/referents.py
   pypy/branch/32ptr-on-64bit/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/32ptr-on-64bit/pypy/module/signal/interp_signal.py
   pypy/branch/32ptr-on-64bit/pypy/module/sys/__init__.py
   pypy/branch/32ptr-on-64bit/pypy/module/sys/state.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/celldict.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/dictmultiobject.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/fake.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/model.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/objspace.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/sharingdict.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringobject.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringtype.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_dictmultiobject.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_shadowtracking.py
   pypy/branch/32ptr-on-64bit/pypy/objspace/std/typeobject.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/_rsocket_rffi.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/rmmap.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/rstring.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rsocket.py
   pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rstring.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rbuilder.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/module/ll_time.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/rbuilder.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/rtyper.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rbuilder.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rclass.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track5.s
   pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/src/signals.h
   pypy/branch/32ptr-on-64bit/pypy/translator/goal/ann_override.py
   pypy/branch/32ptr-on-64bit/pypy/translator/jvm/test/test_class.py
   pypy/branch/32ptr-on-64bit/pypy/translator/oosupport/test_template/class_.py
Log:
Merge trunk up to r77829.


Modified: pypy/branch/32ptr-on-64bit/pypy/annotation/policy.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/annotation/policy.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/annotation/policy.py	Tue Oct 12 14:42:59 2010
@@ -1,4 +1,4 @@
-# base annotation policy for overrides and specialization
+# base annotation policy for specialization
 from pypy.annotation.specialize import default_specialize as default
 from pypy.annotation.specialize import specialize_argvalue, specialize_argtype, specialize_arglistitemtype
 from pypy.annotation.specialize import memo
@@ -41,7 +41,7 @@
         if directive is None:
             return pol.default_specialize
 
-        # specialize|override:name[(args)]
+        # specialize[(args)]
         directive_parts = directive.split('(', 1)
         if len(directive_parts) == 1:
             [name] = directive_parts
@@ -60,14 +60,6 @@
         except AttributeError:
             raise AttributeError("%r specialize tag not defined in annotation"
                                  "policy %s" % (name, pol))
-        if directive.startswith('override:'):
-            # different signature: override__xyz(*args_s)
-            if parms:
-                raise Exception, "override:* specialisations don't support parameters"
-            def specialize_override(funcdesc, args_s):
-                funcdesc.overridden = True
-                return specializer(*args_s)
-            return specialize_override
         else:
             if not parms:
                 return specializer
@@ -92,9 +84,5 @@
         from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
         return LowLevelAnnotatorPolicy.specialize__ll_and_arg(*args)
 
-    def override__ignore(pol, *args):
-        bk = getbookkeeper()
-        return bk.immutablevalue(None)
-
 class StrictAnnotatorPolicy(AnnotatorPolicy):
     allow_someobjects = False

Modified: pypy/branch/32ptr-on-64bit/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/annotation/test/test_annrpython.py	Tue Oct 12 14:42:59 2010
@@ -766,28 +766,6 @@
         s = a.build_types(f, [list])
         assert s.classdef is a.bookkeeper.getuniqueclassdef(IndexError)  # KeyError ignored because l is a list
 
-    def test_overrides(self):
-        excs = []
-        def record_exc(e):
-            """NOT_RPYTHON"""
-            excs.append(sys.exc_info)
-        record_exc._annspecialcase_ = "override:record_exc"
-        def g():
-            pass
-        def f():
-            try:
-                g()
-            except Exception, e:
-                record_exc(e)
-        class MyAnnotatorPolicy(policy.AnnotatorPolicy):
-
-            def override__record_exc(pol, s_e):
-                return a.bookkeeper.immutablevalue(None)
-            
-        a = self.RPythonAnnotator(policy=MyAnnotatorPolicy())
-        s = a.build_types(f, [])
-        assert s.const is None
-
     def test_freeze_protocol(self):
         class Stuff:
             def __init__(self, flag):

Modified: pypy/branch/32ptr-on-64bit/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/config/pypyoption.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/config/pypyoption.py	Tue Oct 12 14:42:59 2010
@@ -198,6 +198,9 @@
         BoolOption("withstrslice", "use strings optimized for slicing",
                    default=False),
 
+        BoolOption("withstrbuf", "use strings optimized for addition (ver 2)",
+                   default=False),
+
         BoolOption("withprebuiltchar",
                    "use prebuilt single-character string objects",
                    default=False),
@@ -210,7 +213,8 @@
         BoolOption("withrope", "use ropes as the string implementation",
                    default=False,
                    requires=[("objspace.std.withstrslice", False),
-                             ("objspace.std.withstrjoin", False)],
+                             ("objspace.std.withstrjoin", False),
+                             ("objspace.std.withstrbuf", False)],
                    suggests=[("objspace.std.withprebuiltchar", True),
                              ("objspace.std.sharesmallstr", True)]),
 
@@ -238,6 +242,16 @@
                    default=False,
                    requires=[("objspace.std.withshadowtracking", False)]),
 
+        BoolOption("withmapdict",
+                   "make instances really small but slow without the JIT",
+                   default=False,
+                   requires=[("objspace.std.withshadowtracking", False),
+                             ("objspace.std.withinlineddict", False),
+                             ("objspace.std.withsharingdict", False),
+                             ("objspace.std.getattributeshortcut", True),
+                             ("objspace.std.withtypeversion", True),
+                       ]),
+
         BoolOption("withrangelist",
                    "enable special range list implementation that does not "
                    "actually create the full list until the resulting "
@@ -343,7 +357,7 @@
         config.objspace.std.suggest(withprebuiltint=True)
         config.objspace.std.suggest(withrangelist=True)
         config.objspace.std.suggest(withprebuiltchar=True)
-        config.objspace.std.suggest(withinlineddict=True)
+        config.objspace.std.suggest(withmapdict=True)
         config.objspace.std.suggest(withstrslice=True)
         config.objspace.std.suggest(withstrjoin=True)
         # xxx other options? ropes maybe?
@@ -359,6 +373,7 @@
     # extra optimizations with the JIT
     if level == 'jit':
         config.objspace.std.suggest(withcelldict=True)
+        #config.objspace.std.suggest(withmapdict=True)
 
 
 def enable_allworkingmodules(config):

Modified: pypy/branch/32ptr-on-64bit/pypy/doc/docindex.txt
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/doc/docindex.txt	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/doc/docindex.txt	Tue Oct 12 14:42:59 2010
@@ -84,7 +84,7 @@
 
 PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure.
 You can also find CPython's compliance tests run with compiled ``pypy-c``
-exeuctables there.
+executables there.
 
 information dating from early 2007: 
 

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/astcompiler/test/test_compiler.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/astcompiler/test/test_compiler.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/astcompiler/test/test_compiler.py	Tue Oct 12 14:42:59 2010
@@ -41,7 +41,7 @@
         co_expr = compile(evalexpr, '<evalexpr>', 'eval')
         space = self.space
         pyco_expr = PyCode._from_code(space, co_expr)
-        w_res = pyco_expr.exec_code(space, w_dict, w_dict)
+        w_res = pyco_expr.exec_host_bytecode(space, w_dict, w_dict)
         res = space.str_w(space.repr(w_res))
         if not isinstance(expected, float):
             assert res == repr(expected)

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/baseobjspace.py	Tue Oct 12 14:42:59 2010
@@ -168,6 +168,20 @@
     def _call_builtin_destructor(self):
         pass     # method overridden in typedef.py
 
+    # hooks that the mapdict implementations needs:
+    def _get_mapdict_map(self):
+        return None
+    def _set_mapdict_map(self, map):
+        raise NotImplementedError
+    def _mapdict_read_storage(self, index):
+        raise NotImplementedError
+    def _mapdict_write_storage(self, index, value):
+        raise NotImplementedError
+    def _mapdict_storage_length(self):
+        raise NotImplementedError
+    def _set_mapdict_storage_and_map(self, storage, map):
+        raise NotImplementedError
+
 
 class Wrappable(W_Root):
     """A subclass of Wrappable is an internal, interpreter-level class

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/pycode.py	Tue Oct 12 14:42:59 2010
@@ -117,6 +117,10 @@
 
         self._compute_flatcall()
 
+        if self.space.config.objspace.std.withmapdict:
+            from pypy.objspace.std.mapdict import init_mapdict_cache
+            init_mapdict_cache(self)
+
     def _freeze_(self):
         if (self.magic == cpython_magic and
             '__pypy__' not in sys.builtin_module_names):
@@ -253,6 +257,12 @@
                          tuple(self.co_freevars),
                          tuple(self.co_cellvars) )
 
+    def exec_host_bytecode(self, w_dict, w_globals, w_locals):
+        from pypy.interpreter.pyframe import CPythonFrame
+        frame = CPythonFrame(self.space, self, w_globals, None)
+        frame.setdictscope(w_locals)
+        return frame.run()
+
     def dump(self):
         """A dis.dis() dump of the code object."""
         co = self._to_code()

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/pyframe.py	Tue Oct 12 14:42:59 2010
@@ -13,6 +13,7 @@
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib import jit, rstack
 from pypy.tool import stdlib_opcode
+from pypy.tool.stdlib_opcode import host_bytecode_spec
 
 # Define some opcodes used
 g = globals()
@@ -140,7 +141,8 @@
         # the following 'assert' is an annotation hint: it hides from
         # the annotator all methods that are defined in PyFrame but
         # overridden in the {,Host}FrameClass subclasses of PyFrame.
-        assert isinstance(self, self.space.FrameClass)
+        assert (isinstance(self, self.space.FrameClass) or
+                not self.space.config.translating)
         executioncontext = self.space.getexecutioncontext()
         executioncontext.enter(self)
         try:
@@ -634,6 +636,18 @@
             return space.wrap(self.builtin is not space.builtin)
         return space.w_False
 
+class CPythonFrame(PyFrame):
+    """
+    Execution of host (CPython) opcodes.
+    """
+
+    bytecode_spec = host_bytecode_spec
+    opcode_method_names = host_bytecode_spec.method_names
+    opcodedesc = host_bytecode_spec.opcodedesc
+    opdescmap = host_bytecode_spec.opdescmap
+    HAVE_ARGUMENT = host_bytecode_spec.HAVE_ARGUMENT
+
+
 # ____________________________________________________________
 
 def get_block_class(opname):

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/pyopcode.py	Tue Oct 12 14:42:59 2010
@@ -710,9 +710,14 @@
 
     def LOAD_ATTR(self, nameindex, next_instr):
         "obj.attributename"
-        w_attributename = self.getname_w(nameindex)
         w_obj = self.popvalue()
-        w_value = self.space.getattr(w_obj, w_attributename)
+        if (self.space.config.objspace.std.withmapdict
+            and not jit.we_are_jitted()):
+            from pypy.objspace.std.mapdict import LOAD_ATTR_caching
+            w_value = LOAD_ATTR_caching(self.getcode(), w_obj, nameindex)
+        else:
+            w_attributename = self.getname_w(nameindex)
+            w_value = self.space.getattr(w_obj, w_attributename)
         self.pushvalue(w_value)
     LOAD_ATTR._always_inline_ = True
 

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/pytokenize.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/pytokenize.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/pyparser/pytokenize.py	Tue Oct 12 14:42:59 2010
@@ -21,40 +21,42 @@
 __all__ = [ "tokenize" ]
 
 # ______________________________________________________________________
-# Automatically generated DFA's (with one or two hand tweeks):
-pseudoStatesAccepts = [True, True, True, True, True, True, True, True,
-                       True, True, False, True, True, True, False, False,
-                       False, False, True, False, False, True, True, False,
-                       True, False, True, False, True, False, True, False,
-                       False, False, True, False, False, False, True]
-
-pseudoStates = [
-    {'\t': 0, '\n': 13, '\x0c': 0, '\r': 14, ' ': 0, '!': 10,
-     '"': 16, '#': 18, '%': 12, '&': 12,
-     "'": 15, '(': 13, ')': 13, '*': 7,
-     '+': 12, ',': 13, '-': 12, '.': 6,
-     '/': 11, '0': 4, '1': 5, '2': 5,
-     '3': 5, '4': 5, '5': 5, '6': 5,
-     '7': 5, '8': 5, '9': 5, ':': 13,
-     ';': 13, '<': 9, '=': 12, '>': 8,
-     '@': 13, 'A': 1,
-     'B': 1, 'C': 1, 'D': 1, 'E': 1,
-     'F': 1, 'G': 1, 'H': 1, 'I': 1,
-     'J': 1, 'K': 1, 'L': 1, 'M': 1,
-     'N': 1, 'O': 1, 'P': 1, 'Q': 1,
-     'R': 2, 'S': 1, 'T': 1, 'U': 3,
-     'V': 1, 'W': 1, 'X': 1, 'Y': 1,
-     'Z': 1, '[': 13, '\\': 17, ']': 13,
-     '^': 12, '_': 1, '`': 13, 'a': 1,
-     'b': 1, 'c': 1, 'd': 1, 'e': 1,
-     'f': 1, 'g': 1, 'h': 1, 'i': 1,
-     'j': 1, 'k': 1, 'l': 1, 'm': 1,
-     'n': 1, 'o': 1, 'p': 1, 'q': 1,
-     'r': 2, 's': 1, 't': 1, 'u': 3,
-     'v': 1, 'w': 1, 'x': 1, 'y': 1,
-     'z': 1, '{': 13, '|': 12, '}': 13,
-     '~': 13},
+# Automatically generated DFA's
 
+accepts = [True, True, True, True, True, True, True, True,
+           True, True, False, True, True, True, False, False,
+           False, False, True, True, True, False, True,
+           False, True, False, True, False, False, True,
+           False, False, False, False, True, False, False,
+           False, True]
+states = [
+    # 0
+    {'\t': 0, '\n': 13, '\x0c': 0,
+     '\r': 14, ' ': 0, '!': 10, '"': 16,
+     '#': 18, '%': 12, '&': 12, "'": 15,
+     '(': 13, ')': 13, '*': 7, '+': 12,
+     ',': 13, '-': 12, '.': 6, '/': 11,
+     '0': 4, '1': 5, '2': 5, '3': 5,
+     '4': 5, '5': 5, '6': 5, '7': 5,
+     '8': 5, '9': 5, ':': 13, ';': 13,
+     '<': 9, '=': 12, '>': 8, '@': 13,
+     'A': 1, 'B': 1, 'C': 1, 'D': 1,
+     'E': 1, 'F': 1, 'G': 1, 'H': 1,
+     'I': 1, 'J': 1, 'K': 1, 'L': 1,
+     'M': 1, 'N': 1, 'O': 1, 'P': 1,
+     'Q': 1, 'R': 2, 'S': 1, 'T': 1,
+     'U': 3, 'V': 1, 'W': 1, 'X': 1,
+     'Y': 1, 'Z': 1, '[': 13, '\\': 17,
+     ']': 13, '^': 12, '_': 1, '`': 13,
+     'a': 1, 'b': 1, 'c': 1, 'd': 1,
+     'e': 1, 'f': 1, 'g': 1, 'h': 1,
+     'i': 1, 'j': 1, 'k': 1, 'l': 1,
+     'm': 1, 'n': 1, 'o': 1, 'p': 1,
+     'q': 1, 'r': 2, 's': 1, 't': 1,
+     'u': 3, 'v': 1, 'w': 1, 'x': 1,
+     'y': 1, 'z': 1, '{': 13, '|': 12,
+     '}': 13, '~': 13},
+    # 1
     {'0': 1, '1': 1, '2': 1, '3': 1,
      '4': 1, '5': 1, '6': 1, '7': 1,
      '8': 1, '9': 1, 'A': 1, 'B': 1,
@@ -71,7 +73,7 @@
      'p': 1, 'q': 1, 'r': 1, 's': 1,
      't': 1, 'u': 1, 'v': 1, 'w': 1,
      'x': 1, 'y': 1, 'z': 1},
-
+    # 2
     {'"': 16, "'": 15, '0': 1, '1': 1,
      '2': 1, '3': 1, '4': 1, '5': 1,
      '6': 1, '7': 1, '8': 1, '9': 1,
@@ -89,7 +91,7 @@
      'r': 1, 's': 1, 't': 1, 'u': 1,
      'v': 1, 'w': 1, 'x': 1, 'y': 1,
      'z': 1},
-
+    # 3
     {'"': 16, "'": 15, '0': 1, '1': 1,
      '2': 1, '3': 1, '4': 1, '5': 1,
      '6': 1, '7': 1, '8': 1, '9': 1,
@@ -107,158 +109,182 @@
      'r': 2, 's': 1, 't': 1, 'u': 1,
      'v': 1, 'w': 1, 'x': 1, 'y': 1,
      'z': 1},
-
-    {'.': 24, '0': 22, '1': 22, '2': 22,
-     '3': 22, '4': 22, '5': 22, '6': 22,
-     '7': 22, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'L': 13, 'X': 21, 'e': 25,
-     'j': 13, 'l': 13, 'x': 21},
-
-    {'.': 24, '0': 5, '1': 5, '2': 5,
+    # 4
+    {'.': 22, '0': 20, '1': 20, '2': 20,
+     '3': 20, '4': 20, '5': 20, '6': 20,
+     '7': 20, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'L': 13, 'X': 19, 'e': 23,
+     'j': 13, 'l': 13, 'x': 19},
+    # 5
+    {'.': 22, '0': 5, '1': 5, '2': 5,
      '3': 5, '4': 5, '5': 5, '6': 5,
-     '7': 5, '8': 5, '9': 5, 'E': 25,
-     'J': 13, 'L': 13, 'e': 25, 'j': 13,
+     '7': 5, '8': 5, '9': 5, 'E': 23,
+     'J': 13, 'L': 13, 'e': 23, 'j': 13,
      'l': 13},
-
-    {'0': 26, '1': 26, '2': 26, '3': 26,
-     '4': 26, '5': 26, '6': 26, '7': 26,
-     '8': 26, '9': 26},
-
+    # 6
+    {'0': 24, '1': 24, '2': 24, '3': 24,
+     '4': 24, '5': 24, '6': 24, '7': 24,
+     '8': 24, '9': 24},
+    # 7
     {'*': 12, '=': 13},
-
+    # 8
     {'=': 13, '>': 12},
-
-    {'=': 13, '<': 12, '>': 13},
-
+    # 9
+    {'<': 12, '=': 13, '>': 13},
+    # 10
     {'=': 13},
-
-    {'=': 13, '/': 12},
-
+    # 11
+    {'/': 12, '=': 13},
+    # 12
     {'=': 13},
-
+    # 13
     {},
-
+    # 14
     {'\n': 13},
-
-    {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 28},
-
-    {automata.DEFAULT: 20, '"': 30, '\n': 27, '\\': 31},
-
+    # 15
+    {automata.DEFAULT: 28, '\n': 25, "'": 26, '\\': 27},
+    # 16
+    {automata.DEFAULT: 31, '\n': 25, '"': 29, '\\': 30},
+    # 17
     {'\n': 13, '\r': 14},
-
-    {automata.DEFAULT: 18, '\n': 27, '\r': 27},
-
-    {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 13},
-
-    {automata.DEFAULT: 20, '"': 13, '\n': 27, '\\': 31},
-                
-    {'0': 21, '1': 21, '2': 21, '3': 21,
-     '4': 21, '5': 21, '6': 21, '7': 21,
-     '8': 21, '9': 21, 'A': 21, 'B': 21,
-     'C': 21, 'D': 21, 'E': 21, 'F': 21,
-     'L': 13, 'a': 21, 'b': 21, 'c': 21,
-     'd': 21, 'e': 21, 'f': 21, 'l': 13},
-    
-    {'.': 24, '0': 22, '1': 22, '2': 22,
-     '3': 22, '4': 22, '5': 22, '6': 22,
-     '7': 22, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'L': 13, 'e': 25, 'j': 13,
+    # 18
+    {automata.DEFAULT: 18, '\n': 25, '\r': 25},
+    # 19
+    {'0': 19, '1': 19, '2': 19, '3': 19,
+     '4': 19, '5': 19, '6': 19, '7': 19,
+     '8': 19, '9': 19, 'A': 19, 'B': 19,
+     'C': 19, 'D': 19, 'E': 19, 'F': 19,
+     'L': 13, 'a': 19, 'b': 19, 'c': 19,
+     'd': 19, 'e': 19, 'f': 19, 'l': 13},
+    # 20
+    {'.': 22, '0': 20, '1': 20, '2': 20,
+     '3': 20, '4': 20, '5': 20, '6': 20,
+     '7': 20, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'L': 13, 'e': 23, 'j': 13,
      'l': 13},
-    
-    {'.': 24, '0': 23, '1': 23, '2': 23,
-     '3': 23, '4': 23, '5': 23, '6': 23,
-     '7': 23, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'e': 25, 'j': 13},
-    
-    {'0': 24, '1': 24, '2': 24, '3': 24,
-     '4': 24, '5': 24, '6': 24, '7': 24,
-     '8': 24, '9': 24, 'E': 32, 'J': 13,
+    # 21
+    {'.': 22, '0': 21, '1': 21, '2': 21,
+     '3': 21, '4': 21, '5': 21, '6': 21,
+     '7': 21, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'e': 23, 'j': 13},
+    # 22
+    {'0': 22, '1': 22, '2': 22, '3': 22,
+     '4': 22, '5': 22, '6': 22, '7': 22,
+     '8': 22, '9': 22, 'E': 32, 'J': 13,
      'e': 32, 'j': 13},
-    
+    # 23
     {'+': 33, '-': 33, '0': 34, '1': 34,
      '2': 34, '3': 34, '4': 34, '5': 34,
      '6': 34, '7': 34, '8': 34, '9': 34},
-    
-    {'0': 26, '1': 26, '2': 26, '3': 26,
-     '4': 26, '5': 26, '6': 26, '7': 26,
-     '8': 26, '9': 26, 'E': 32, 'J': 13,
+    # 24
+    {'0': 24, '1': 24, '2': 24, '3': 24,
+     '4': 24, '5': 24, '6': 24, '7': 24,
+     '8': 24, '9': 24, 'E': 32, 'J': 13,
      'e': 32, 'j': 13},
-    
+    # 25
     {},
-
+    # 26
     {"'": 13},
-
+    # 27
     {automata.DEFAULT: 35, '\n': 13, '\r': 14},
-
+    # 28
+    {automata.DEFAULT: 28, '\n': 25, "'": 13, '\\': 27},
+    # 29
     {'"': 13},
-
+    # 30
     {automata.DEFAULT: 36, '\n': 13, '\r': 14},
-
+    # 31
+    {automata.DEFAULT: 31, '\n': 25, '"': 13, '\\': 30},
+    # 32
     {'+': 37, '-': 37, '0': 38, '1': 38,
      '2': 38, '3': 38, '4': 38, '5': 38,
      '6': 38, '7': 38, '8': 38, '9': 38},
-    
-    
+    # 33
     {'0': 34, '1': 34, '2': 34, '3': 34,
      '4': 34, '5': 34, '6': 34, '7': 34,
      '8': 34, '9': 34},
-    
+    # 34
     {'0': 34, '1': 34, '2': 34, '3': 34,
      '4': 34, '5': 34, '6': 34, '7': 34,
      '8': 34, '9': 34, 'J': 13, 'j': 13},
-    
-    {automata.DEFAULT: 35, '\n': 27, '\\': 29, "'": 13},
-    
-    {automata.DEFAULT: 36, '"': 13, '\n': 27, '\\': 31},
-    
+    # 35
+    {automata.DEFAULT: 35, '\n': 25, "'": 13, '\\': 27},
+    # 36
+    {automata.DEFAULT: 36, '\n': 25, '"': 13, '\\': 30},
+    # 37
     {'0': 38, '1': 38, '2': 38, '3': 38,
      '4': 38, '5': 38, '6': 38, '7': 38,
      '8': 38, '9': 38},
-
+    # 38
     {'0': 38, '1': 38, '2': 38, '3': 38,
      '4': 38, '5': 38, '6': 38, '7': 38,
      '8': 38, '9': 38, 'J': 13, 'j': 13},
     ]
+pseudoDFA = automata.DFA(states, accepts)
 
-pseudoDFA = automata.DFA(pseudoStates, pseudoStatesAccepts)
-
-double3StatesAccepts = [False, False, False, False, False, True]
-double3States = [
+accepts = [False, False, False, False, False, True]
+states = [
+    # 0
     {automata.DEFAULT: 0, '"': 1, '\\': 2},
+    # 1
     {automata.DEFAULT: 4, '"': 3, '\\': 2},
+    # 2
     {automata.DEFAULT: 4},
+    # 3
     {automata.DEFAULT: 4, '"': 5, '\\': 2},
+    # 4
     {automata.DEFAULT: 4, '"': 1, '\\': 2},
+    # 5
     {automata.DEFAULT: 4, '"': 5, '\\': 2},
     ]
-double3DFA = automata.NonGreedyDFA(double3States, double3StatesAccepts)
+double3DFA = automata.NonGreedyDFA(states, accepts)
 
-single3StatesAccepts = [False, False, False, False, False, True]
-single3States = [
-    {automata.DEFAULT: 0, '\\': 2, "'": 1},
-    {automata.DEFAULT: 4, '\\': 2, "'": 3},
+accepts = [False, False, False, False, False, True]
+states = [
+    # 0
+    {automata.DEFAULT: 0, "'": 1, '\\': 2},
+    # 1
+    {automata.DEFAULT: 4, "'": 3, '\\': 2},
+    # 2
     {automata.DEFAULT: 4},
-    {automata.DEFAULT: 4, '\\': 2, "'": 5},
-    {automata.DEFAULT: 4, '\\': 2, "'": 1},
-    {automata.DEFAULT: 4, '\\': 2, "'": 5},
+    # 3
+    {automata.DEFAULT: 4, "'": 5, '\\': 2},
+    # 4
+    {automata.DEFAULT: 4, "'": 1, '\\': 2},
+    # 5
+    {automata.DEFAULT: 4, "'": 5, '\\': 2},
     ]
-single3DFA = automata.NonGreedyDFA(single3States, single3StatesAccepts)
+single3DFA = automata.NonGreedyDFA(states, accepts)
 
-singleStatesAccepts = [False, True, False]
-singleStates = [
-    {automata.DEFAULT: 0, '\\': 2, "'": 1},
+accepts = [False, True, False, False]
+states = [
+    # 0
+    {automata.DEFAULT: 0, "'": 1, '\\': 2},
+    # 1
     {},
-    {automata.DEFAULT: 0},
+    # 2
+    {automata.DEFAULT: 3},
+    # 3
+    {automata.DEFAULT: 3, "'": 1, '\\': 2},
     ]
-singleDFA = automata.DFA(singleStates, singleStatesAccepts)
+singleDFA = automata.DFA(states, accepts)
 
-doubleStatesAccepts = [False, True, False]
-doubleStates = [
+accepts = [False, True, False, False]
+states = [
+    # 0
     {automata.DEFAULT: 0, '"': 1, '\\': 2},
+    # 1
     {},
-    {automata.DEFAULT: 0},
+    # 2
+    {automata.DEFAULT: 3},
+    # 3
+    {automata.DEFAULT: 3, '"': 1, '\\': 2},
     ]
-doubleDFA = automata.DFA(doubleStates, doubleStatesAccepts)
+doubleDFA = automata.DFA(states, accepts)
+
+
+#_______________________________________________________________________
+# End of automatically generated DFA's
 
 endDFAs = {"'" : singleDFA,
            '"' : doubleDFA,

Modified: pypy/branch/32ptr-on-64bit/pypy/interpreter/typedef.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/interpreter/typedef.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/interpreter/typedef.py	Tue Oct 12 14:42:59 2010
@@ -133,6 +133,13 @@
     typedef = cls.typedef
     if wants_dict and typedef.hasdict:
         wants_dict = False
+    if config.objspace.std.withmapdict and not typedef.hasdict:
+        # mapdict only works if the type does not already have a dict
+        if wants_del:
+            parentcls = get_unique_interplevel_subclass(config, cls, True, True,
+                                                        False, True)
+            return _usersubclswithfeature(config, parentcls, "del")
+        return _usersubclswithfeature(config, cls, "user", "dict", "weakref", "slots")
     # Forest of if's - see the comment above.
     if wants_del:
         if wants_dict:
@@ -186,10 +193,20 @@
 
     def add(Proto):
         for key, value in Proto.__dict__.items():
-            if not key.startswith('__') or key == '__del__':
+            if (not key.startswith('__') and not key.startswith('_mixin_') 
+                    or key == '__del__'):
+                if hasattr(value, "func_name"):
+                    value = func_with_new_name(value, value.func_name)
                 body[key] = value
 
+    if (config.objspace.std.withmapdict and "dict" in features):
+        from pypy.objspace.std.mapdict import BaseMapdictObject, ObjectMixin
+        add(BaseMapdictObject)
+        add(ObjectMixin)
+        features = ()
+
     if "user" in features:     # generic feature needed by all subcls
+
         class Proto(object):
             user_overridden_class = True
 
@@ -255,6 +272,9 @@
             wantdict = False
 
     if wantdict:
+        base_user_setup = supercls.user_setup.im_func
+        if "user_setup" in body:
+            base_user_setup = body["user_setup"]
         class Proto(object):
             def getdict(self):
                 return self.w__dict__
@@ -263,11 +283,9 @@
                 self.w__dict__ = check_new_dictionary(space, w_dict)
             
             def user_setup(self, space, w_subtype):
-                self.space = space
-                self.w__class__ = w_subtype
                 self.w__dict__ = space.newdict(
                     instance=True, classofinstance=w_subtype)
-                self.user_setup_slots(w_subtype.nslots)
+                base_user_setup(self, space, w_subtype)
 
             def setclass(self, space, w_subtype):
                 # only used by descr_set___class__

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/runner_test.py	Tue Oct 12 14:42:59 2010
@@ -833,6 +833,23 @@
                                                         length_box], 'void')
                                 assert self.look_string(r_box) == "!??cdef?!"
 
+    def test_copyunicodecontent(self):
+        s_box = self.alloc_unicode(u"abcdef")
+        for s_box in [s_box, s_box.constbox()]:
+            for srcstart_box in [BoxInt(2), ConstInt(2)]:
+                for dststart_box in [BoxInt(3), ConstInt(3)]:
+                    for length_box in [BoxInt(4), ConstInt(4)]:
+                        for r_box_is_const in [False, True]:
+                            r_box = self.alloc_unicode(u"!???????!")
+                            if r_box_is_const:
+                                r_box = r_box.constbox()
+                                self.execute_operation(rop.COPYUNICODECONTENT,
+                                                       [s_box, r_box,
+                                                        srcstart_box,
+                                                        dststart_box,
+                                                        length_box], 'void')
+                                assert self.look_unicode(r_box) == u"!??cdef?!"
+
     def test_do_unicode_basic(self):
         u = self.cpu.bh_newunicode(5)
         self.cpu.bh_unicodesetitem(u, 4, 123)
@@ -1227,6 +1244,10 @@
         u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u))
         return u_box
 
+    def look_unicode(self, unicode_box):
+        u = unicode_box.getref(lltype.Ptr(rstr.UNICODE))
+        return u''.join(u.chars)
+
 
     def test_casts(self):
         py.test.skip("xxx fix or kill")

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/test_ll_random.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/test_ll_random.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/test/test_ll_random.py	Tue Oct 12 14:42:59 2010
@@ -599,7 +599,7 @@
     OPERATIONS.append(StrLenOperation(rop.STRLEN))
     OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN))
     OPERATIONS.append(CopyStrContentOperation(rop.COPYSTRCONTENT))
-    #OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
+    OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
 
 for i in range(2):
     OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS))

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/assembler.py	Tue Oct 12 14:42:59 2010
@@ -244,7 +244,7 @@
             f = open_file_as_stream(output_log, "w")
             for i in range(len(self.loop_run_counters)):
                 name, struct = self.loop_run_counters[i]
-                f.write(str(struct.i) + " " * (8 - len(str(struct.i))) + name + "\n")
+                f.write(str(name) + ":" +  str(struct.i) + "\n")
             f.close()
 
     def _build_float_constants(self):
@@ -401,7 +401,7 @@
         if self._debug:
             struct = lltype.malloc(DEBUG_COUNTER, flavor='raw')
             struct.i = 0
-            self.loop_run_counters.append((funcname, struct))
+            self.loop_run_counters.append((len(self.loop_run_counters), struct))
         return funcname
         
     def patch_jump_for_descr(self, faildescr, adr_new_target):

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/regalloc.py	Tue Oct 12 14:42:59 2010
@@ -778,15 +778,11 @@
             loc = self.loc(op.getarg(0))
             return self._call(op, [loc])
         # boehm GC (XXX kill the following code at some point)
-        ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code)
-        if itemsize == 4:
-            return self._malloc_varsize(ofs_items, ofs, 2, op.getarg(0),
-                                        op.result)
-        elif itemsize == 2:
-            return self._malloc_varsize(ofs_items, ofs, 1, op.getarg(0),
-                                        op.result)
-        else:
-            assert False, itemsize
+        ofs_items, _, ofs = symbolic.get_array_token(rstr.UNICODE,
+                                                   self.translate_support_code)
+        scale = self._get_unicode_item_scale()
+        return self._malloc_varsize(ofs_items, ofs, scale, op.getarg(0),
+                                    op.result)
 
     def _malloc_varsize(self, ofs_items, ofs_length, scale, v, res_v):
         # XXX kill this function at some point
@@ -959,6 +955,12 @@
     consider_unicodegetitem = consider_strgetitem
 
     def consider_copystrcontent(self, op):
+        self._consider_copystrcontent(op, is_unicode=False)
+
+    def consider_copyunicodecontent(self, op):
+        self._consider_copystrcontent(op, is_unicode=True)
+
+    def _consider_copystrcontent(self, op, is_unicode):
         # compute the source address
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(args[0], args)
@@ -970,7 +972,8 @@
         srcaddr_box = TempBox()
         forbidden_vars = [args[1], args[3], args[4], srcaddr_box]
         srcaddr_loc = self.rm.force_allocate_reg(srcaddr_box, forbidden_vars)
-        self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc)
+        self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc,
+                                        is_unicode=is_unicode)
         # compute the destination address
         base_loc = self.rm.make_sure_var_in_reg(args[1], forbidden_vars)
         ofs_loc = self.rm.make_sure_var_in_reg(args[3], forbidden_vars)
@@ -980,25 +983,57 @@
         forbidden_vars = [args[4], srcaddr_box]
         dstaddr_box = TempBox()
         dstaddr_loc = self.rm.force_allocate_reg(dstaddr_box, forbidden_vars)
-        self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc)
+        self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc,
+                                        is_unicode=is_unicode)
+        # compute the length in bytes
+        length_box = args[4]
+        length_loc = self.loc(length_box)
+        if is_unicode:
+            self.rm.possibly_free_var(length_box)
+            forbidden_vars = [srcaddr_box, dstaddr_box]
+            bytes_box = TempBox()
+            bytes_loc = self.rm.force_allocate_reg(bytes_box, forbidden_vars)
+            scale = self._get_unicode_item_scale()
+            if not (isinstance(length_loc, ImmedLoc) or
+                    isinstance(length_loc, RegLoc)):
+                self.assembler.mov(length_loc, bytes_loc)
+                length_loc = bytes_loc
+            self.assembler.load_effective_addr(length_loc, 0, scale, bytes_loc)
+            length_box = bytes_box
+            length_loc = bytes_loc
         # call memcpy()
-        length_loc = self.loc(args[4])
         self.rm.before_call()
         self.xrm.before_call()
         self.assembler._emit_call(imm(self.assembler.memcpy_addr),
                                   [dstaddr_loc, srcaddr_loc, length_loc])
-        self.rm.possibly_free_var(args[4])
+        self.rm.possibly_free_var(length_box)
         self.rm.possibly_free_var(dstaddr_box)
         self.rm.possibly_free_var(srcaddr_box)
 
-    def _gen_address_inside_string(self, baseloc, ofsloc, resloc):
+    def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode):
         cpu = self.assembler.cpu
-        ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
+        if is_unicode:
+            ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE,
+                                                  self.translate_support_code)
+            scale = self._get_unicode_item_scale()
+        else:
+            ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
                                                   self.translate_support_code)
-        assert itemsize == 1
-        self.assembler.load_effective_addr(ofsloc, ofs_items, 0,
+            assert itemsize == 1
+            scale = 0
+        self.assembler.load_effective_addr(ofsloc, ofs_items, scale,
                                            resloc, baseloc)
 
+    def _get_unicode_item_scale(self):
+        _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
+                                                  self.translate_support_code)
+        if itemsize == 4:
+            return 2
+        elif itemsize == 2:
+            return 1
+        else:
+            raise AssertionError("bad unicode item size")
+
     def consider_jump(self, op):
         assembler = self.assembler
         assert self.jump_target_descr is None

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_runner.py	Tue Oct 12 14:42:59 2010
@@ -506,8 +506,8 @@
         self.cpu.execute_token(ops.token)
         # check debugging info
         name, struct = self.cpu.assembler.loop_run_counters[0]
-        assert name == 'xyz'
+        assert name == 0       # 'xyz'
         assert struct.i == 10
         self.cpu.finish_once()
         lines = py.path.local(self.logfile + ".count").readlines()
-        assert lines[0] == '10      xyz\n'
+        assert lines[0] == '0:10\n'  # '10      xyz\n'

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_string.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_string.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/backend/x86/test/test_string.py	Tue Oct 12 14:42:59 2010
@@ -2,8 +2,12 @@
 from pypy.jit.metainterp.test import test_string
 from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
 
-class TestString(Jit386Mixin, test_string.StringTests):
+class TestString(Jit386Mixin, test_string.TestLLtype):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_string.py
-    CALL = 'call'
-    CALL_PURE = 'call_pure'
+    pass
+
+class TestUnicode(Jit386Mixin, test_string.TestLLtypeUnicode):
+    # for the individual tests see
+    # ====> ../../../metainterp/test/test_string.py
+    pass

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/effectinfo.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/effectinfo.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/effectinfo.py	Tue Oct 12 14:42:59 2010
@@ -18,19 +18,30 @@
     # the 'oopspecindex' field is one of the following values:
     OS_NONE                     = 0    # normal case, no oopspec
     OS_ARRAYCOPY                = 1    # "list.ll_arraycopy"
-    OS_STR_CONCAT               = 2    # "stroruni.concat"
-    OS_UNI_CONCAT               = 3    # "stroruni.concat"
-    OS_STR_SLICE                = 4    # "stroruni.slice"
-    OS_UNI_SLICE                = 5    # "stroruni.slice"
-    OS_STR_EQUAL                = 6    # "stroruni.equal"
-    OS_UNI_EQUAL                = 7    # "stroruni.equal"
-    OS_STREQ_SLICE_CHECKNULL    = 8    # s2!=NULL and s1[x:x+length]==s2
-    OS_STREQ_SLICE_NONNULL      = 9    # s1[x:x+length]==s2   (assert s2!=NULL)
-    OS_STREQ_SLICE_CHAR         = 10   # s1[x:x+length]==char
-    OS_STREQ_NONNULL            = 11   # s1 == s2    (assert s1!=NULL,s2!=NULL)
-    OS_STREQ_NONNULL_CHAR       = 12   # s1 == char  (assert s1!=NULL)
-    OS_STREQ_CHECKNULL_CHAR     = 13   # s1!=NULL and s1==char
-    OS_STREQ_LENGTHOK           = 14   # s1 == s2    (assert len(s1)==len(s2))
+    OS_STR2UNICODE              = 2    # "str.str2unicode"
+
+    OS_STR_CONCAT               = 22   # "stroruni.concat"
+    OS_STR_SLICE                = 23   # "stroruni.slice"
+    OS_STR_EQUAL                = 24   # "stroruni.equal"
+    OS_STREQ_SLICE_CHECKNULL    = 25   # s2!=NULL and s1[x:x+length]==s2
+    OS_STREQ_SLICE_NONNULL      = 26   # s1[x:x+length]==s2   (assert s2!=NULL)
+    OS_STREQ_SLICE_CHAR         = 27   # s1[x:x+length]==char
+    OS_STREQ_NONNULL            = 28   # s1 == s2    (assert s1!=NULL,s2!=NULL)
+    OS_STREQ_NONNULL_CHAR       = 29   # s1 == char  (assert s1!=NULL)
+    OS_STREQ_CHECKNULL_CHAR     = 30   # s1!=NULL and s1==char
+    OS_STREQ_LENGTHOK           = 31   # s1 == s2    (assert len(s1)==len(s2))
+
+    OS_UNI_CONCAT               = 42   #
+    OS_UNI_SLICE                = 43   #
+    OS_UNI_EQUAL                = 44   #
+    OS_UNIEQ_SLICE_CHECKNULL    = 45   #
+    OS_UNIEQ_SLICE_NONNULL      = 46   #
+    OS_UNIEQ_SLICE_CHAR         = 47   #
+    OS_UNIEQ_NONNULL            = 48   #   the same for unicode
+    OS_UNIEQ_NONNULL_CHAR       = 49   #   (must be the same amount as for
+    OS_UNIEQ_CHECKNULL_CHAR     = 50   #   STR, in the same order)
+    OS_UNIEQ_LENGTHOK           = 51   #
+    _OS_offset_uni              = OS_UNI_CONCAT - OS_STR_CONCAT
 
     def __new__(cls, readonly_descrs_fields,
                 write_descrs_fields, write_descrs_arrays,

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/jtransform.py	Tue Oct 12 14:42:59 2010
@@ -316,6 +316,8 @@
             prepare = self._handle_list_call
         elif oopspec_name.startswith('stroruni.'):
             prepare = self._handle_stroruni_call
+        elif oopspec_name == 'str.str2unicode':
+            prepare = self._handle_str2unicode_call
         elif oopspec_name.startswith('virtual_ref'):
             prepare = self._handle_virtual_ref_call
         else:
@@ -1106,11 +1108,16 @@
                      [SoU, SoU],
                      lltype.Signed),
                 ]:
+                if args[0].concretetype.TO == rstr.UNICODE:
+                    otherindex += EffectInfo._OS_offset_uni
                 self._register_extra_helper(otherindex, othername,
                                             argtypes, resulttype)
         #
         return self._handle_oopspec_call(op, args, dict[oopspec_name])
 
+    def _handle_str2unicode_call(self, op, oopspec_name, args):
+        return self._handle_oopspec_call(op, args, EffectInfo.OS_STR2UNICODE)
+
     # ----------
     # VirtualRefs.
 

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/test/test_jtransform.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/test/test_jtransform.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/codewriter/test/test_jtransform.py	Tue Oct 12 14:42:59 2010
@@ -77,7 +77,8 @@
 class FakeBuiltinCallControl:
     def guess_call_kind(self, op):
         return 'builtin'
-    def getcalldescr(self, op, oopspecindex):
+    def getcalldescr(self, op, oopspecindex=None):
+        assert oopspecindex is not None    # in this test
         return 'calldescr-%d' % oopspecindex
     def calldescr_canraise(self, calldescr):
         return False
@@ -766,6 +767,24 @@
     assert op1.args[3] == ListOfKind('ref', [v1])
     assert op1.result == v4
 
+def test_str2unicode():
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    PUNICODE = lltype.Ptr(rstr.UNICODE)
+    FUNC = lltype.FuncType([PSTR], PUNICODE)
+    func = lltype.functionptr(FUNC, 'll_str2unicode',
+                            _callable=rstr.LLHelpers.ll_str2unicode)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(PUNICODE)
+    op = SpaceOperation('direct_call', [const(func), v1], v2)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_r_r'
+    assert op1.args[0].value == func
+    assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_STR2UNICODE
+    assert op1.args[2] == ListOfKind('ref', [v1])
+    assert op1.result == v2
+
 def test_list_ll_arraycopy():
     from pypy.rlib.rgc import ll_arraycopy
     LIST = lltype.GcArray(lltype.Signed)

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/history.py	Tue Oct 12 14:42:59 2010
@@ -698,6 +698,21 @@
     return result
 _const_ptr_for_string = {}
 
+def get_const_ptr_for_unicode(s):
+    from pypy.rpython.annlowlevel import llunicode
+    if not we_are_translated():
+        try:
+            return _const_ptr_for_unicode[s]
+        except KeyError:
+            pass
+    if isinstance(s, str):
+        s = unicode(s)
+    result = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, llunicode(s)))
+    if not we_are_translated():
+        _const_ptr_for_unicode[s] = result
+    return result
+_const_ptr_for_unicode = {}
+
 # ____________________________________________________________
 
 # The TreeLoop class contains a loop or a generalized loop, i.e. a tree

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimize_nopspec.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimize_nopspec.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimize_nopspec.py	Tue Oct 12 14:42:59 2010
@@ -14,6 +14,9 @@
 def _optimize_loop(metainterp_sd, old_loop_tokens, loop):
     cpu = metainterp_sd.cpu
     metainterp_sd.logger_noopt.log_loop(loop.inputargs, loop.operations)
+    # XXX the following lines are probably still needed, to discard invalid
+    # loops. bit silly to run a full perfect specialization and throw the
+    # result away.
     finder = PerfectSpecializationFinder(cpu)
     finder.find_nodes_loop(loop, False)
     if old_loop_tokens:
@@ -31,6 +34,7 @@
 def _optimize_bridge(metainterp_sd, old_loop_tokens, bridge):
     cpu = metainterp_sd.cpu    
     metainterp_sd.logger_noopt.log_loop(bridge.inputargs, bridge.operations)
+    # XXX same comment as above applies
     finder = BridgeSpecializationFinder(cpu)
     finder.find_nodes_bridge(bridge)
     if old_loop_tokens:

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/intbounds.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/intbounds.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/intbounds.py	Tue Oct 12 14:42:59 2010
@@ -191,6 +191,7 @@
         v1.intbound.make_ge(IntLowerBound(0))
 
     optimize_STRLEN = optimize_ARRAYLEN_GC
+    optimize_UNICODELEN = optimize_ARRAYLEN_GC
 
     def make_int_lt(self, box1, box2):
         v1 = self.getvalue(box1)

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/rewrite.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/rewrite.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/rewrite.py	Tue Oct 12 14:42:59 2010
@@ -3,6 +3,7 @@
 from pypy.jit.metainterp.history import ConstInt
 from pypy.jit.metainterp.optimizeutil import _findall
 from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.codewriter.effectinfo import EffectInfo
 
 class OptRewrite(Optimization):
     """Rewrite operations into equivalent, cheaper operations.
@@ -245,6 +246,9 @@
     def optimize_CALL_LOOPINVARIANT(self, op):
         funcvalue = self.getvalue(op.getarg(0))
         if not funcvalue.is_constant():
+            # XXX this code path is never executed in tests nor in production.
+            # in fact, it can't even happen since residual_call in codewriter
+            # expects a compile-time constant
             self.emit_operation(op)
             return
         key = make_hashable_int(op.getarg(0).getint())
@@ -323,8 +327,37 @@
 ##            return
 ##        self.emit_operation(op)
 
-optimize_ops = _findall(OptRewrite, 'optimize_')
-        
+    def optimize_CALL(self, op):
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.  For non-oopspec calls,
+        # oopspecindex is just zero.
+        effectinfo = op.getdescr().get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            if oopspecindex == EffectInfo.OS_ARRAYCOPY:
+                if self._optimize_CALL_ARRAYCOPY(op):
+                    return
+        self.emit_operation(op)
 
+    def _optimize_CALL_ARRAYCOPY(self, op):
+        source_value = self.getvalue(op.getarg(1))
+        dest_value = self.getvalue(op.getarg(2))
+        source_start_box = self.get_constant_box(op.getarg(3))
+        dest_start_box = self.get_constant_box(op.getarg(4))
+        length = self.get_constant_box(op.getarg(5))
+        if (source_value.is_virtual() and source_start_box and dest_start_box
+            and length and dest_value.is_virtual()):
+            # XXX optimize the case where dest value is not virtual,
+            #     but we still can avoid a mess
+            source_start = source_start_box.getint()
+            dest_start = dest_start_box.getint()
+            for index in range(length.getint()):
+                val = source_value.getitem(index + source_start)
+                dest_value.setitem(index + dest_start, val)
+            return True
+        if length and length.getint() == 0:
+            return True # 0-length arraycopy
+        return False
+
+optimize_ops = _findall(OptRewrite, 'optimize_')
 
-        

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/string.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/string.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/optimizeopt/string.py	Tue Oct 12 14:42:59 2010
@@ -3,6 +3,7 @@
 from pypy.jit.metainterp.history import Box, BoxInt, BoxPtr
 from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr
 from pypy.jit.metainterp.history import get_const_ptr_for_string
+from pypy.jit.metainterp.history import get_const_ptr_for_unicode
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
 from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
@@ -11,56 +12,103 @@
 from pypy.jit.codewriter.effectinfo import EffectInfo, callinfo_for_oopspec
 from pypy.jit.codewriter import heaptracker
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import specialize
+
+
+class StrOrUnicode(object):
+    def __init__(self, LLTYPE, hlstr, emptystr, chr,
+                 NEWSTR, STRLEN, STRGETITEM, STRSETITEM, COPYSTRCONTENT,
+                 OS_offset):
+        self.LLTYPE = LLTYPE
+        self.hlstr = hlstr
+        self.emptystr = emptystr
+        self.chr = chr
+        self.NEWSTR = NEWSTR
+        self.STRLEN = STRLEN
+        self.STRGETITEM = STRGETITEM
+        self.STRSETITEM = STRSETITEM
+        self.COPYSTRCONTENT = COPYSTRCONTENT
+        self.OS_offset = OS_offset
+
+    def _freeze_(self):
+        return True
+
+mode_string = StrOrUnicode(rstr.STR, annlowlevel.hlstr, '', chr,
+                           rop.NEWSTR, rop.STRLEN, rop.STRGETITEM,
+                           rop.STRSETITEM, rop.COPYSTRCONTENT, 0)
+mode_unicode = StrOrUnicode(rstr.UNICODE, annlowlevel.hlunicode, u'', unichr,
+                            rop.NEWUNICODE, rop.UNICODELEN, rop.UNICODEGETITEM,
+                            rop.UNICODESETITEM, rop.COPYUNICODECONTENT,
+                            EffectInfo._OS_offset_uni)
+
+# ____________________________________________________________
 
 
 class __extend__(optimizer.OptValue):
     """New methods added to the base class OptValue for this file."""
 
-    def getstrlen(self, newoperations):
-        s = self.get_constant_string()
-        if s is not None:
-            return ConstInt(len(s))
+    def getstrlen(self, newoperations, mode):
+        if mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                return ConstInt(len(s))
         else:
-            if newoperations is None:
-                return None
-            self.ensure_nonnull()
-            box = self.force_box()
-            lengthbox = BoxInt()
-            newoperations.append(ResOperation(rop.STRLEN, [box], lengthbox))
-            return lengthbox
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                return ConstInt(len(s))
+        if newoperations is None:
+            return None
+        self.ensure_nonnull()
+        box = self.force_box()
+        lengthbox = BoxInt()
+        newoperations.append(ResOperation(mode.STRLEN, [box], lengthbox))
+        return lengthbox
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         if self.is_constant():
-            s = self.box.getref(lltype.Ptr(rstr.STR))
-            return annlowlevel.hlstr(s)
+            s = self.box.getref(lltype.Ptr(mode.LLTYPE))
+            return mode.hlstr(s)
         else:
             return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         # Copies the pointer-to-string 'self' into the target string
         # given by 'targetbox', at the specified offset.  Returns the offset
         # at the end of the copy.
-        lengthbox = self.getstrlen(newoperations)
+        lengthbox = self.getstrlen(newoperations, mode)
         srcbox = self.force_box()
         return copy_str_content(newoperations, srcbox, targetbox,
-                                CONST_0, offsetbox, lengthbox)
+                                CONST_0, offsetbox, lengthbox, mode)
 
 
 class VAbstractStringValue(virtualize.AbstractVirtualValue):
-    _attrs_ = ()
+    _attrs_ = ('mode',)
+
+    def __init__(self, optimizer, keybox, source_op, mode):
+        virtualize.AbstractVirtualValue.__init__(self, optimizer, keybox,
+                                                 source_op)
+        self.mode = mode
 
     def _really_force(self):
-        s = self.get_constant_string()
-        if s is not None:
-            c_s = get_const_ptr_for_string(s)
-            self.make_constant(c_s)
-            return
+        if self.mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                c_s = get_const_ptr_for_string(s)
+                self.make_constant(c_s)
+                return
+        else:
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                c_s = get_const_ptr_for_unicode(s)
+                self.make_constant(c_s)
+                return
         assert self.source_op is not None
         self.box = box = self.source_op.result
         newoperations = self.optimizer.newoperations
-        lengthbox = self.getstrlen(newoperations)
-        newoperations.append(ResOperation(rop.NEWSTR, [lengthbox], box))
-        self.string_copy_parts(newoperations, box, CONST_0)
+        lengthbox = self.getstrlen(newoperations, self.mode)
+        newoperations.append(ResOperation(self.mode.NEWSTR, [lengthbox], box))
+        self.string_copy_parts(newoperations, box, CONST_0, self.mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
@@ -74,7 +122,7 @@
         assert 0 <= start <= stop <= len(longerlist)
         self._chars = longerlist[start:stop]
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         if self._lengthbox is None:
             self._lengthbox = ConstInt(len(self._chars))
         return self._lengthbox
@@ -86,18 +134,21 @@
         assert isinstance(charvalue, optimizer.OptValue)
         self._chars[index] = charvalue
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         for c in self._chars:
             if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
                 return None
-        return ''.join([chr(c.box.getint()) for c in self._chars])
+        return mode.emptystr.join([mode.chr(c.box.getint())
+                                   for c in self._chars])
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         for i in range(len(self._chars)):
             charbox = self._chars[i].force_box()
-            newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
-                                                               offsetbox,
-                                                               charbox], None))
+            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+                                                                offsetbox,
+                                                                charbox],
+                                              None))
             offsetbox = _int_add(newoperations, offsetbox, CONST_1)
         return offsetbox
 
@@ -109,7 +160,7 @@
                 value.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrplain()
+        return modifier.make_vstrplain(self.mode is mode_unicode)
 
 
 class VStringConcatValue(VAbstractStringValue):
@@ -120,23 +171,24 @@
         self.right = right
         self.lengthbox = lengthbox
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         return self.lengthbox
 
-    def get_constant_string(self):
-        s1 = self.left.get_constant_string()
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
+        s1 = self.left.get_constant_string_spec(mode)
         if s1 is None:
             return None
-        s2 = self.right.get_constant_string()
+        s2 = self.right.get_constant_string_spec(mode)
         if s2 is None:
             return None
         return s1 + s2
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         offsetbox = self.left.string_copy_parts(newoperations, targetbox,
-                                                offsetbox)
+                                                offsetbox, mode)
         offsetbox = self.right.string_copy_parts(newoperations, targetbox,
-                                                 offsetbox)
+                                                 offsetbox, mode)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
@@ -150,7 +202,7 @@
             self.right.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrconcat()
+        return modifier.make_vstrconcat(self.mode is mode_unicode)
 
 
 class VStringSliceValue(VAbstractStringValue):
@@ -162,12 +214,13 @@
         self.vstart = vstart
         self.vlength = vlength
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         return self.vlength.force_box()
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         if self.vstart.is_constant() and self.vlength.is_constant():
-            s1 = self.vstr.get_constant_string()
+            s1 = self.vstr.get_constant_string_spec(mode)
             if s1 is None:
                 return None
             start = self.vstart.box.getint()
@@ -177,12 +230,12 @@
             return s1[start : start + length]
         return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
-        lengthbox = self.getstrlen(newoperations)
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+        lengthbox = self.getstrlen(newoperations, mode)
         return copy_str_content(newoperations,
                                 self.vstr.force_box(), targetbox,
                                 self.vstart.force_box(), offsetbox,
-                                lengthbox)
+                                lengthbox, mode)
 
     def get_args_for_fail(self, modifier):
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
@@ -195,11 +248,11 @@
             self.vlength.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrslice()
+        return modifier.make_vstrslice(self.mode is mode_unicode)
 
 
 def copy_str_content(newoperations, srcbox, targetbox,
-                     srcoffsetbox, offsetbox, lengthbox):
+                     srcoffsetbox, offsetbox, lengthbox, mode):
     if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
         M = 5
     else:
@@ -208,17 +261,18 @@
         # up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
         # instead of just a COPYSTRCONTENT.
         for i in range(lengthbox.value):
-            charbox = _strgetitem(newoperations, srcbox, srcoffsetbox)
+            charbox = _strgetitem(newoperations, srcbox, srcoffsetbox, mode)
             srcoffsetbox = _int_add(newoperations, srcoffsetbox, CONST_1)
-            newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
-                                                               offsetbox,
-                                                               charbox], None))
+            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+                                                                offsetbox,
+                                                                charbox],
+                                              None))
             offsetbox = _int_add(newoperations, offsetbox, CONST_1)
     else:
         nextoffsetbox = _int_add(newoperations, offsetbox, lengthbox)
-        op = ResOperation(rop.COPYSTRCONTENT, [srcbox, targetbox,
-                                               srcoffsetbox, offsetbox,
-                                               lengthbox], None)
+        op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
+                                                srcoffsetbox, offsetbox,
+                                                lengthbox], None)
         newoperations.append(op)
         offsetbox = nextoffsetbox
     return offsetbox
@@ -245,12 +299,16 @@
     newoperations.append(ResOperation(rop.INT_SUB, [box1, box2], resbox))
     return resbox
 
-def _strgetitem(newoperations, strbox, indexbox):
+def _strgetitem(newoperations, strbox, indexbox, mode):
     if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
-        s = strbox.getref(lltype.Ptr(rstr.STR))
-        return ConstInt(ord(s.chars[indexbox.getint()]))
+        if mode is mode_string:
+            s = strbox.getref(lltype.Ptr(rstr.STR))
+            return ConstInt(ord(s.chars[indexbox.getint()]))
+        else:
+            s = strbox.getref(lltype.Ptr(rstr.UNICODE))
+            return ConstInt(ord(s.chars[indexbox.getint()]))
     resbox = BoxInt()
-    newoperations.append(ResOperation(rop.STRGETITEM, [strbox, indexbox],
+    newoperations.append(ResOperation(mode.STRGETITEM, [strbox, indexbox],
                                       resbox))
     return resbox
 
@@ -258,62 +316,34 @@
 class OptString(optimizer.Optimization):
     "Handling of strings and unicodes."
 
-    def make_vstring_plain(self, box, source_op=None):
-        vvalue = VStringPlainValue(self.optimizer, box, source_op)
+    def make_vstring_plain(self, box, source_op, mode):
+        vvalue = VStringPlainValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_vstring_concat(self, box, source_op=None):
-        vvalue = VStringConcatValue(self.optimizer, box, source_op)
+    def make_vstring_concat(self, box, source_op, mode):
+        vvalue = VStringConcatValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_vstring_slice(self, box, source_op=None):
-        vvalue = VStringSliceValue(self.optimizer, box, source_op)
+    def make_vstring_slice(self, box, source_op, mode):
+        vvalue = VStringSliceValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def optimize_CALL(self, op):
-        # dispatch based on 'oopspecindex' to a method that handles
-        # specifically the given oopspec call.  For non-oopspec calls,
-        # oopspecindex is just zero.
-        effectinfo = op.getdescr().get_extra_info()
-        if effectinfo is not None:
-            oopspecindex = effectinfo.oopspecindex
-            for value, meth in opt_call_oopspec_ops:
-                if oopspecindex == value:
-                    if meth(self, op):
-                        return
-        self.emit_operation(op)
-
-    def opt_call_oopspec_ARRAYCOPY(self, op):
-        source_value = self.getvalue(op.getarg(1))
-        dest_value = self.getvalue(op.getarg(2))
-        source_start_box = self.get_constant_box(op.getarg(3))
-        dest_start_box = self.get_constant_box(op.getarg(4))
-        length = self.get_constant_box(op.getarg(5))
-        if (source_value.is_virtual() and source_start_box and dest_start_box
-            and length and dest_value.is_virtual()):
-            # XXX optimize the case where dest value is not virtual,
-            #     but we still can avoid a mess
-            source_start = source_start_box.getint()
-            dest_start = dest_start_box.getint()
-            for index in range(length.getint()):
-                val = source_value.getitem(index + source_start)
-                dest_value.setitem(index + dest_start, val)
-            return True
-        if length and length.getint() == 0:
-            return True # 0-length arraycopy
-        return False
-
     def optimize_NEWSTR(self, op):
+        self._optimize_NEWSTR(op, mode_string)
+    def optimize_NEWUNICODE(self, op):
+        self._optimize_NEWSTR(op, mode_unicode)
+
+    def _optimize_NEWSTR(self, op, mode):
         length_box = self.get_constant_box(op.getarg(0))
         if length_box:
             # if the original 'op' did not have a ConstInt as argument,
             # build a new one with the ConstInt argument
             if not isinstance(op.getarg(0), ConstInt):
-                op = ResOperation(rop.NEWSTR, [length_box], op.result)
-            vvalue = self.make_vstring_plain(op.result, op)
+                op = ResOperation(mode.NEWSTR, [length_box], op.result)
+            vvalue = self.make_vstring_plain(op.result, op, mode)
             vvalue.setup(length_box.getint())
         else:
             self.getvalue(op.result).ensure_nonnull()
@@ -329,13 +359,20 @@
         value.ensure_nonnull()
         self.emit_operation(op)
 
+    optimize_UNICODESETITEM = optimize_STRSETITEM
+
     def optimize_STRGETITEM(self, op):
+        self._optimize_STRGETITEM(op, mode_string)
+    def optimize_UNICODEGETITEM(self, op):
+        self._optimize_STRGETITEM(op, mode_unicode)
+
+    def _optimize_STRGETITEM(self, op, mode):
         value = self.getvalue(op.getarg(0))
         vindex = self.getvalue(op.getarg(1))
-        vresult = self.strgetitem(value, vindex)
+        vresult = self.strgetitem(value, vindex, mode)
         self.make_equal_to(op.result, vresult)
 
-    def strgetitem(self, value, vindex):
+    def strgetitem(self, value, vindex, mode):
         value.ensure_nonnull()
         #
         if value.is_virtual() and isinstance(value, VStringSliceValue):
@@ -350,28 +387,71 @@
                 return value.getitem(vindex.box.getint())
         #
         resbox = _strgetitem(self.optimizer.newoperations,
-                             value.force_box(),vindex.force_box())
+                             value.force_box(),vindex.force_box(), mode)
         return self.getvalue(resbox)
 
     def optimize_STRLEN(self, op):
+        self._optimize_STRLEN(op, mode_string)
+    def optimize_UNICODELEN(self, op):
+        self._optimize_STRLEN(op, mode_unicode)
+
+    def _optimize_STRLEN(self, op, mode):
         value = self.getvalue(op.getarg(0))
-        lengthbox = value.getstrlen(self.optimizer.newoperations)
+        lengthbox = value.getstrlen(self.optimizer.newoperations, mode)
         self.make_equal_to(op.result, self.getvalue(lengthbox))
 
-    def opt_call_oopspec_STR_CONCAT(self, op):
+    def optimize_CALL(self, op):
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.  For non-oopspec calls,
+        # oopspecindex is just zero.
+        effectinfo = op.getdescr().get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            for value, meth in opt_call_oopspec_ops:
+                if oopspecindex == value:      # a match with the OS_STR_xxx
+                    if meth(self, op, mode_string):
+                        return
+                    break
+                if oopspecindex == value + EffectInfo._OS_offset_uni:
+                    # a match with the OS_UNI_xxx
+                    if meth(self, op, mode_unicode):
+                        return
+                    break
+            if oopspecindex == EffectInfo.OS_STR2UNICODE:
+                if self.opt_call_str_STR2UNICODE(op):
+                    return
+        self.emit_operation(op)
+
+    def opt_call_str_STR2UNICODE(self, op):
+        # Constant-fold unicode("constant string").
+        # More generally, supporting non-constant but virtual cases is
+        # not obvious, because of the exception UnicodeDecodeError that
+        # can be raised by ll_str2unicode()
+        varg = self.getvalue(op.getarg(1))
+        s = varg.get_constant_string_spec(mode_string)
+        if s is None:
+            return False
+        try:
+            u = unicode(s)
+        except UnicodeDecodeError:
+            return False
+        self.make_constant(op.result, get_const_ptr_for_unicode(u))
+        return True
+
+    def opt_call_stroruni_STR_CONCAT(self, op, mode):
         vleft = self.getvalue(op.getarg(1))
         vright = self.getvalue(op.getarg(2))
         vleft.ensure_nonnull()
         vright.ensure_nonnull()
         newoperations = self.optimizer.newoperations
-        len1box = vleft.getstrlen(newoperations)
-        len2box = vright.getstrlen(newoperations)
+        len1box = vleft.getstrlen(newoperations, mode)
+        len2box = vright.getstrlen(newoperations, mode)
         lengthbox = _int_add(newoperations, len1box, len2box)
-        value = self.make_vstring_concat(op.result, op)
+        value = self.make_vstring_concat(op.result, op, mode)
         value.setup(vleft, vright, lengthbox)
         return True
 
-    def opt_call_oopspec_STR_SLICE(self, op):
+    def opt_call_stroruni_STR_SLICE(self, op, mode):
         newoperations = self.optimizer.newoperations
         vstr = self.getvalue(op.getarg(1))
         vstart = self.getvalue(op.getarg(2))
@@ -380,7 +460,7 @@
         if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
             and vstop.is_constant()):
             # slicing with constant bounds of a VStringPlainValue
-            value = self.make_vstring_plain(op.result, op)
+            value = self.make_vstring_plain(op.result, op, mode)
             value.setup_slice(vstr._chars, vstart.box.getint(),
                                            vstop.box.getint())
             return True
@@ -398,16 +478,16 @@
                                 vstart.force_box())
             vstart = self.getvalue(startbox)
         #
-        value = self.make_vstring_slice(op.result, op)
+        value = self.make_vstring_slice(op.result, op, mode)
         value.setup(vstr, vstart, self.getvalue(lengthbox))
         return True
 
-    def opt_call_oopspec_STR_EQUAL(self, op):
+    def opt_call_stroruni_STR_EQUAL(self, op, mode):
         v1 = self.getvalue(op.getarg(1))
         v2 = self.getvalue(op.getarg(2))
         #
-        l1box = v1.getstrlen(None)
-        l2box = v2.getstrlen(None)
+        l1box = v1.getstrlen(None, mode)
+        l2box = v2.getstrlen(None, mode)
         if (l1box is not None and l2box is not None and
             isinstance(l1box, ConstInt) and
             isinstance(l2box, ConstInt) and
@@ -416,13 +496,13 @@
             self.make_constant(op.result, CONST_0)
             return True
         #
-        if self.handle_str_equal_level1(v1, v2, op.result):
+        if self.handle_str_equal_level1(v1, v2, op.result, mode):
             return True
-        if self.handle_str_equal_level1(v2, v1, op.result):
+        if self.handle_str_equal_level1(v2, v1, op.result, mode):
             return True
-        if self.handle_str_equal_level2(v1, v2, op.result):
+        if self.handle_str_equal_level2(v1, v2, op.result, mode):
             return True
-        if self.handle_str_equal_level2(v2, v1, op.result):
+        if self.handle_str_equal_level2(v2, v1, op.result, mode):
             return True
         #
         if v1.is_nonnull() and v2.is_nonnull():
@@ -434,37 +514,37 @@
             else:
                 do = EffectInfo.OS_STREQ_NONNULL
             self.generate_modified_call(do, [v1.force_box(),
-                                             v2.force_box()], op.result)
+                                             v2.force_box()], op.result, mode)
             return True
         return False
 
-    def handle_str_equal_level1(self, v1, v2, resultbox):
-        l2box = v2.getstrlen(None)
+    def handle_str_equal_level1(self, v1, v2, resultbox, mode):
+        l2box = v2.getstrlen(None, mode)
         if isinstance(l2box, ConstInt):
             if l2box.value == 0:
-                lengthbox = v1.getstrlen(self.optimizer.newoperations)
+                lengthbox = v1.getstrlen(self.optimizer.newoperations, mode)
                 seo = self.optimizer.send_extra_operation
                 seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
                 return True
             if l2box.value == 1:
-                l1box = v1.getstrlen(None)
+                l1box = v1.getstrlen(None, mode)
                 if isinstance(l1box, ConstInt) and l1box.value == 1:
                     # comparing two single chars
-                    vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO)
-                    vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                    vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO, mode)
+                    vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                     seo = self.optimizer.send_extra_operation
                     seo(ResOperation(rop.INT_EQ, [vchar1.force_box(),
                                                   vchar2.force_box()],
                                      resultbox))
                     return True
                 if isinstance(v1, VStringSliceValue):
-                    vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                    vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                     do = EffectInfo.OS_STREQ_SLICE_CHAR
                     self.generate_modified_call(do, [v1.vstr.force_box(),
                                                      v1.vstart.force_box(),
                                                      v1.vlength.force_box(),
                                                      vchar.force_box()],
-                                                resultbox)
+                                                resultbox, mode)
                     return True
         #
         if v2.is_null():
@@ -482,17 +562,18 @@
         #
         return False
 
-    def handle_str_equal_level2(self, v1, v2, resultbox):
-        l2box = v2.getstrlen(None)
+    def handle_str_equal_level2(self, v1, v2, resultbox, mode):
+        l2box = v2.getstrlen(None, mode)
         if isinstance(l2box, ConstInt):
             if l2box.value == 1:
-                vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                 if v1.is_nonnull():
                     do = EffectInfo.OS_STREQ_NONNULL_CHAR
                 else:
                     do = EffectInfo.OS_STREQ_CHECKNULL_CHAR
                 self.generate_modified_call(do, [v1.force_box(),
-                                                 vchar.force_box()], resultbox)
+                                                 vchar.force_box()], resultbox,
+                                            mode)
                 return True
         #
         if v1.is_virtual() and isinstance(v1, VStringSliceValue):
@@ -503,11 +584,12 @@
             self.generate_modified_call(do, [v1.vstr.force_box(),
                                              v1.vstart.force_box(),
                                              v1.vlength.force_box(),
-                                             v2.force_box()], resultbox)
+                                             v2.force_box()], resultbox, mode)
             return True
         return False
 
-    def generate_modified_call(self, oopspecindex, args, result):
+    def generate_modified_call(self, oopspecindex, args, result, mode):
+        oopspecindex += mode.OS_offset
         calldescr, func = callinfo_for_oopspec(oopspecindex)
         op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
                           descr=calldescr)
@@ -525,7 +607,7 @@
 optimize_ops = _findall(OptString, 'optimize_')
 
 def _findall_call_oopspec():
-    prefix = 'opt_call_oopspec_'
+    prefix = 'opt_call_stroruni_'
     result = []
     for name in dir(OptString):
         if name.startswith(prefix):

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/resume.py	Tue Oct 12 14:42:59 2010
@@ -255,13 +255,19 @@
     def make_varray(self, arraydescr):
         return VArrayInfo(arraydescr)
 
-    def make_vstrplain(self):
+    def make_vstrplain(self, is_unicode=False):
+        if is_unicode:
+            return VUniPlainInfo()
         return VStrPlainInfo()
 
-    def make_vstrconcat(self):
+    def make_vstrconcat(self, is_unicode=False):
+        if is_unicode:
+            return VUniConcatInfo()
         return VStrConcatInfo()
 
-    def make_vstrslice(self):
+    def make_vstrslice(self, is_unicode=False):
+        if is_unicode:
+            return VUniSliceInfo()
         return VStrSliceInfo()
 
     def register_virtual_fields(self, virtualbox, fieldboxes):
@@ -550,6 +556,60 @@
         for i in self.fieldnums:
             debug_print("\t\t", str(untag(i)))
 
+
+class VUniPlainInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of the characters of all
+    fieldnums."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        length = len(self.fieldnums)
+        string = decoder.allocate_unicode(length)
+        decoder.virtuals_cache[index] = string
+        for i in range(length):
+            decoder.unicode_setitem(string, i, self.fieldnums[i])
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvuniplaininfo length", len(self.fieldnums))
+
+
+class VUniConcatInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of the concatenation of two
+    other unicode strings."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        # xxx for blackhole resuming, this will build all intermediate
+        # strings and throw them away immediately, which is a bit sub-
+        # efficient.  Not sure we care.
+        left, right = self.fieldnums
+        string = decoder.concat_unicodes(left, right)
+        decoder.virtuals_cache[index] = string
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvuniconcatinfo")
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
+
+class VUniSliceInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of slicing another
+    unicode string."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        largerstr, start, length = self.fieldnums
+        string = decoder.slice_unicode(largerstr, start, length)
+        decoder.virtuals_cache[index] = string
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvunisliceinfo")
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
 # ____________________________________________________________
 
 class AbstractResumeDataReader(object):
@@ -725,6 +785,32 @@
         return self.metainterp.execute_and_record_varargs(
             rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
 
+    def allocate_unicode(self, length):
+        return self.metainterp.execute_and_record(rop.NEWUNICODE,
+                                                  None, ConstInt(length))
+
+    def unicode_setitem(self, strbox, index, charnum):
+        charbox = self.decode_box(charnum, INT)
+        self.metainterp.execute_and_record(rop.UNICODESETITEM, None,
+                                           strbox, ConstInt(index), charbox)
+
+    def concat_unicodes(self, str1num, str2num):
+        calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+        str1box = self.decode_box(str1num, REF)
+        str2box = self.decode_box(str2num, REF)
+        return self.metainterp.execute_and_record_varargs(
+            rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
+
+    def slice_unicode(self, strnum, startnum, lengthnum):
+        calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
+        strbox = self.decode_box(strnum, REF)
+        startbox = self.decode_box(startnum, INT)
+        lengthbox = self.decode_box(lengthnum, INT)
+        stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
+                                                     startbox, lengthbox)
+        return self.metainterp.execute_and_record_varargs(
+            rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
+
     def setfield(self, descr, structbox, fieldnum):
         if descr.is_pointer_field():
             kind = REF
@@ -967,6 +1053,31 @@
         result = funcptr(str, start, start + length)
         return lltype.cast_opaque_ptr(llmemory.GCREF, result)
 
+    def allocate_unicode(self, length):
+        return self.cpu.bh_newunicode(length)
+
+    def unicode_setitem(self, str, index, charnum):
+        char = self.decode_int(charnum)
+        self.cpu.bh_unicodesetitem(str, index, char)
+
+    def concat_unicodes(self, str1num, str2num):
+        str1 = self.decode_ref(str1num)
+        str2 = self.decode_ref(str2num)
+        str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1)
+        str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2)
+        funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+        result = funcptr(str1, str2)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
+    def slice_unicode(self, strnum, startnum, lengthnum):
+        str = self.decode_ref(strnum)
+        start = self.decode_int(startnum)
+        length = self.decode_int(lengthnum)
+        str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str)
+        funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
+        result = funcptr(str, start, start + length)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
     def setfield(self, descr, struct, fieldnum):
         if descr.is_pointer_field():
             newvalue = self.decode_ref(fieldnum)

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/simple_optimize.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/simple_optimize.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/simple_optimize.py	Tue Oct 12 14:42:59 2010
@@ -9,11 +9,13 @@
 
 def transform(op):
     from pypy.jit.metainterp.history import AbstractDescr
-    # Rename CALL_PURE to CALL.
+    # Rename CALL_PURE and CALL_LOOPINVARIANT to CALL.
     # Simplify the VIRTUAL_REF_* so that they don't show up in the backend.
     if op.getopnum() == rop.CALL_PURE:
         op = ResOperation(rop.CALL, op.getarglist()[1:], op.result,
                           op.getdescr())
+    elif op.getopnum() == rop.CALL_LOOPINVARIANT:
+        op = op.copy_and_change(rop.CALL)
     elif op.getopnum() == rop.VIRTUAL_REF:
         op = ResOperation(rop.SAME_AS, [op.getarg(0)], op.result)
     elif op.getopnum() == rop.VIRTUAL_REF_FINISH:

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/oparser.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/oparser.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/oparser.py	Tue Oct 12 14:42:59 2010
@@ -5,7 +5,7 @@
 
 from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\
      ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\
-     LoopToken, get_const_ptr_for_string
+     LoopToken, get_const_ptr_for_string, get_const_ptr_for_unicode
 from pypy.jit.metainterp.resoperation import rop, ResOperation, ResOpWithDescr, N_aryOp
 from pypy.jit.metainterp.typesystem import llhelper
 from pypy.jit.codewriter.heaptracker import adr2int
@@ -158,10 +158,15 @@
         except ValueError:
             if self.is_float(arg):
                 return ConstFloat(float(arg))
-            if arg.startswith('"') or arg.startswith("'"):
+            if (arg.startswith('"') or arg.startswith("'") or
+                arg.startswith('s"')):
                 # XXX ootype
-                info = arg.strip("'\"")
+                info = arg[1:].strip("'\"")
                 return get_const_ptr_for_string(info)
+            if arg.startswith('u"'):
+                # XXX ootype
+                info = arg[1:].strip("'\"")
+                return get_const_ptr_for_unicode(info)
             if arg.startswith('ConstClass('):
                 name = arg[len('ConstClass('):-1]
                 return self.get_const(name, 'class')

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizefindnode.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizefindnode.py	Tue Oct 12 14:42:59 2010
@@ -117,33 +117,32 @@
                             EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE))
     arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                  EffectInfo([], [], [], oopspecindex=EffectInfo.OS_ARRAYCOPY))
-    strconcatdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_CONCAT))
-    slicedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_SLICE))
-    strequaldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_EQUAL))
-    streq_slice_checknull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_CHECKNULL))
-    streq_slice_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_NONNULL))
-    streq_slice_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_CHAR))
-    streq_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_NONNULL))
-    streq_nonnull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_NONNULL_CHAR))
-    streq_checknull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_CHECKNULL_CHAR))
-    streq_lengthok_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_LENGTHOK))
+
+    for _name, _os in [
+        ('strconcatdescr',               'OS_STR_CONCAT'),
+        ('strslicedescr',                'OS_STR_SLICE'),
+        ('strequaldescr',                'OS_STR_EQUAL'),
+        ('streq_slice_checknull_descr',  'OS_STREQ_SLICE_CHECKNULL'),
+        ('streq_slice_nonnull_descr',    'OS_STREQ_SLICE_NONNULL'),
+        ('streq_slice_char_descr',       'OS_STREQ_SLICE_CHAR'),
+        ('streq_nonnull_descr',          'OS_STREQ_NONNULL'),
+        ('streq_nonnull_char_descr',     'OS_STREQ_NONNULL_CHAR'),
+        ('streq_checknull_char_descr',   'OS_STREQ_CHECKNULL_CHAR'),
+        ('streq_lengthok_descr',         'OS_STREQ_LENGTHOK'),
+        ]:
+        _oopspecindex = getattr(EffectInfo, _os)
+        locals()[_name] = \
+            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=_oopspecindex))
+        #
+        _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
+        locals()[_name.replace('str', 'unicode')] = \
+            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=_oopspecindex))
+
+    s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
+    #
 
     class LoopToken(AbstractDescr):
         pass

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_optimizeopt.py	Tue Oct 12 14:42:59 2010
@@ -3487,7 +3487,7 @@
         i0 = strlen(p0)
         jump(p0)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_addsub_const(self):
         ops = """
@@ -3893,6 +3893,15 @@
         """
         self.optimize_loop(ops, 'Not, Not', expected)
 
+    # ----------
+    def optimize_strunicode_loop(self, ops, spectext, optops):
+        # check with the arguments passed in
+        self.optimize_loop(ops, spectext, optops)
+        # check with replacing 'str' with 'unicode' everywhere
+        self.optimize_loop(ops.replace('str','unicode').replace('s"', 'u"'),
+                           spectext,
+                           optops.replace('str','unicode').replace('s"', 'u"'))
+
     def test_newstr_1(self):
         ops = """
         [i0]
@@ -3905,7 +3914,7 @@
         [i0]
         jump(i0)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_newstr_2(self):
         ops = """
@@ -3921,7 +3930,7 @@
         [i0, i1]
         jump(i1, i0)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_concat_1(self):
         ops = """
@@ -3942,7 +3951,7 @@
         copystrcontent(p2, p3, 0, i4, i5)
         jump(p2, p3)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_concat_vstr2_str(self):
         ops = """
@@ -3965,7 +3974,7 @@
         copystrcontent(p2, p3, 0, 2, i4)
         jump(i1, i0, p3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_vstr2(self):
         ops = """
@@ -3989,7 +3998,7 @@
         i6 = int_add(i5, 1)      # will be killed by the backend
         jump(i1, i0, p3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_str_str(self):
         ops = """
@@ -4016,12 +4025,12 @@
         copystrcontent(p3, p5, 0, i12b, i3b)
         jump(p2, p3, p5)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_cstr1(self):
         ops = """
         [p2]
-        p3 = call(0, p2, "x", descr=strconcatdescr)
+        p3 = call(0, p2, s"x", descr=strconcatdescr)
         jump(p3)
         """
         expected = """
@@ -4035,28 +4044,28 @@
         i5 = int_add(i4, 1)      # will be killed by the backend
         jump(p3)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_str_concat_consts(self):
         ops = """
         []
-        p1 = same_as("ab")
-        p2 = same_as("cde")
+        p1 = same_as(s"ab")
+        p2 = same_as(s"cde")
         p3 = call(0, p1, p2, descr=strconcatdescr)
         escape(p3)
         jump()
         """
         expected = """
         []
-        escape("abcde")
+        escape(s"abcde")
         jump()
         """
-        self.optimize_loop(ops, '', expected)
+        self.optimize_strunicode_loop(ops, '', expected)
 
     def test_str_slice_1(self):
         ops = """
         [p1, i1, i2]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
         jump(p2, i1, i2)
         """
         expected = """
@@ -4066,12 +4075,12 @@
         copystrcontent(p1, p2, i1, 0, i3)
         jump(p2, i1, i2)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_slice_2(self):
         ops = """
         [p1, i2]
-        p2 = call(0, p1, 0, i2, descr=slicedescr)
+        p2 = call(0, p1, 0, i2, descr=strslicedescr)
         jump(p2, i2)
         """
         expected = """
@@ -4080,13 +4089,13 @@
         copystrcontent(p1, p2, 0, 0, i2)
         jump(p2, i2)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_slice_3(self):
         ops = """
         [p1, i1, i2, i3, i4]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
-        p3 = call(0, p2, i3, i4, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
+        p3 = call(0, p2, i3, i4, descr=strslicedescr)
         jump(p3, i1, i2, i3, i4)
         """
         expected = """
@@ -4098,12 +4107,12 @@
         copystrcontent(p1, p3, i6, 0, i5)
         jump(p3, i1, i2, i3, i4)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not, Not', expected)
 
     def test_str_slice_getitem1(self):
         ops = """
         [p1, i1, i2, i3]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
         i4 = strgetitem(p2, i3)
         escape(i4)
         jump(p1, i1, i2, i3)
@@ -4116,7 +4125,7 @@
         escape(i4)
         jump(p1, i1, i2, i3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
 
     def test_str_slice_plain(self):
         ops = """
@@ -4124,7 +4133,7 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i3)
         strsetitem(p1, 1, i4)
-        p2 = call(0, p1, 1, 2, descr=slicedescr)
+        p2 = call(0, p1, 1, 2, descr=strslicedescr)
         i5 = strgetitem(p2, 0)
         escape(i5)
         jump(i3, i4)
@@ -4134,12 +4143,12 @@
         escape(i4)
         jump(i3, i4)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_slice_concat(self):
         ops = """
         [p1, i1, i2, p2]
-        p3 = call(0, p1, i1, i2, descr=slicedescr)
+        p3 = call(0, p1, i1, i2, descr=strslicedescr)
         p4 = call(0, p3, p2, descr=strconcatdescr)
         jump(p4, i1, i2, p2)
         """
@@ -4155,10 +4164,10 @@
         copystrcontent(p2, p4, 0, i3, i4b)
         jump(p4, i1, i2, p2)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
 
     # ----------
-    def optimize_loop_extradescrs(self, ops, spectext, optops):
+    def optimize_strunicode_loop_extradescrs(self, ops, spectext, optops):
         from pypy.jit.metainterp.optimizeopt import string
         def my_callinfo_for_oopspec(oopspecindex):
             calldescrtype = type(LLtypeMixin.strequaldescr)
@@ -4173,7 +4182,7 @@
         saved = string.callinfo_for_oopspec
         try:
             string.callinfo_for_oopspec = my_callinfo_for_oopspec
-            self.optimize_loop(ops, spectext, optops)
+            self.optimize_strunicode_loop(ops, spectext, optops)
         finally:
             string.callinfo_for_oopspec = saved
 
@@ -4184,7 +4193,7 @@
         escape(i0)
         jump(p1, p2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', ops)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', ops)
 
     def test_str_equal_noop2(self):
         ops = """
@@ -4209,12 +4218,13 @@
         escape(i0)
         jump(p1, p2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice1(self):
         ops = """
         [p1, i1, i2, p3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p4, p3, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4226,12 +4236,13 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice2(self):
         ops = """
         [p1, i1, i2, p3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4243,13 +4254,14 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice3(self):
         ops = """
         [p1, i1, i2, p3]
         guard_nonnull(p3) []
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4262,13 +4274,14 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice4(self):
         ops = """
         [p1, i1, i2]
-        p3 = call(0, p1, i1, i2, descr=slicedescr)
-        i0 = call(0, p3, "x", descr=strequaldescr)
+        p3 = call(0, p1, i1, i2, descr=strslicedescr)
+        i0 = call(0, p3, s"x", descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2)
         """
@@ -4279,12 +4292,13 @@
         escape(i0)
         jump(p1, i1, i2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice5(self):
         ops = """
         [p1, i1, i2, i3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         p5 = newstr(1)
         strsetitem(p5, 0, i3)
         i0 = call(0, p5, p4, descr=strequaldescr)
@@ -4298,7 +4312,8 @@
         escape(i0)
         jump(p1, i1, i2, i3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_none1(self):
         ops = """
@@ -4313,7 +4328,7 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_none2(self):
         ops = """
@@ -4328,30 +4343,30 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull1(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "hello world", descr=strequaldescr)
+        i0 = call(0, p1, s"hello world", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
         expected = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "hello world", descr=streq_nonnull_descr)
+        i0 = call(0, p1, s"hello world", descr=streq_nonnull_descr)
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull2(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "", descr=strequaldescr)
+        i0 = call(0, p1, s"", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4363,13 +4378,13 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull3(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "x", descr=strequaldescr)
+        i0 = call(0, p1, s"x", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4380,13 +4395,13 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull4(self):
         ops = """
         [p1, p2]
         p4 = call(0, p1, p2, descr=strconcatdescr)
-        i0 = call(0, "hello world", p4, descr=strequaldescr)
+        i0 = call(0, s"hello world", p4, descr=strequaldescr)
         escape(i0)
         jump(p1, p2)
         """
@@ -4401,17 +4416,17 @@
         i5 = strlen(p2)
         i6 = int_add(i4, i5)      # will be killed by the backend
         copystrcontent(p2, p4, 0, i4, i5)
-        i0 = call(0, "hello world", p4, descr=streq_nonnull_descr)
+        i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
         escape(i0)
         jump(p1, p2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
 
     def test_str_equal_chars0(self):
         ops = """
         [i1]
         p1 = newstr(0)
-        i0 = call(0, p1, "", descr=strequaldescr)
+        i0 = call(0, p1, s"", descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4420,14 +4435,14 @@
         escape(1)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_chars1(self):
         ops = """
         [i1]
         p1 = newstr(1)
         strsetitem(p1, 0, i1)
-        i0 = call(0, p1, "x", descr=strequaldescr)
+        i0 = call(0, p1, s"x", descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4437,7 +4452,7 @@
         escape(i0)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_chars2(self):
         ops = """
@@ -4445,7 +4460,7 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i1)
         strsetitem(p1, 1, i2)
-        i0 = call(0, p1, "xy", descr=strequaldescr)
+        i0 = call(0, p1, s"xy", descr=strequaldescr)
         escape(i0)
         jump(i1, i2)
         """
@@ -4454,16 +4469,16 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i1)
         strsetitem(p1, 1, i2)
-        i0 = call(0, p1, "xy", descr=streq_lengthok_descr)
+        i0 = call(0, p1, s"xy", descr=streq_lengthok_descr)
         escape(i0)
         jump(i1, i2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
 
     def test_str_equal_chars3(self):
         ops = """
         [p1]
-        i0 = call(0, "x", p1, descr=strequaldescr)
+        i0 = call(0, s"x", p1, descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4473,14 +4488,14 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_lengthmismatch1(self):
         ops = """
         [i1]
         p1 = newstr(1)
         strsetitem(p1, 0, i1)
-        i0 = call(0, "xy", p1, descr=strequaldescr)
+        i0 = call(0, s"xy", p1, descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4489,10 +4504,33 @@
         escape(0)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
-    # XXX unicode operations
-    # XXX str2unicode
+    def test_str2unicode_constant(self):
+        ops = """
+        []
+        p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        escape(p0)
+        jump()
+        """
+        expected = """
+        []
+        escape(u"xy")
+        jump()
+        """
+        self.optimize_strunicode_loop_extradescrs(ops, '', expected)
+
+    def test_str2unicode_nonconstant(self):
+        ops = """
+        [p0]
+        p1 = call(0, p0, descr=s2u_descr)      # string -> unicode
+        escape(p1)
+        jump(p1)
+        """
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', ops)
+        # more generally, supporting non-constant but virtual cases is
+        # not obvious, because of the exception UnicodeDecodeError that
+        # can be raised by ll_str2unicode()
 
 
 ##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_resume.py	Tue Oct 12 14:42:59 2010
@@ -240,6 +240,17 @@
         return FakeBuiltObject(strconcat=[left, right])
     def slice_string(self, str, start, length):
         return FakeBuiltObject(strslice=[str, start, length])
+    def allocate_unicode(self, length):
+        return FakeBuiltObject(unistring=[None]*length)
+    def unicode_setitem(self, unistring, i, fieldnum):
+        value, tag = untag(fieldnum)
+        assert tag == TAGINT
+        assert 0 <= i < len(unistring.unistring)
+        unistring.unistring[i] = value
+    def concat_unicodes(self, left, right):
+        return FakeBuiltObject(uniconcat=[left, right])
+    def slice_unicode(self, str, start, length):
+        return FakeBuiltObject(unislice=[str, start, length])
 
 class FakeBuiltObject(object):
     def __init__(self, **kwds):
@@ -304,6 +315,30 @@
     assert reader.force_all_virtuals() == [
         FakeBuiltObject(strslice=info.fieldnums)]
 
+def test_vuniplaininfo():
+    info = VUniPlainInfo()
+    info.fieldnums = [tag(60, TAGINT)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(unistring=[60])]
+
+def test_vuniconcatinfo():
+    info = VUniConcatInfo()
+    info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(uniconcat=info.fieldnums)]
+
+def test_vunisliceinfo():
+    info = VUniSliceInfo()
+    info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX), tag(30, TAGBOX)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(unislice=info.fieldnums)]
+
 # ____________________________________________________________
 
 

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_string.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_string.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/metainterp/test/test_string.py	Tue Oct 12 14:42:59 2010
@@ -6,14 +6,17 @@
 
 
 class StringTests:
+    _str, _chr = str, chr
+
     def test_eq_residual(self):
+        _str = self._str
         jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's'])
-        global_s = "hello"
+        global_s = _str("hello")
         def f(n, b, s):
             if b:
-                s += "ello"
+                s += _str("ello")
             else:
-                s += "allo"
+                s += _str("allo")
             i = 0
             while n > 0:
                 jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -21,18 +24,19 @@
                 n -= 1 + (s == global_s)
                 i += 1
             return i
-        res = self.meta_interp(f, [10, True, 'h'], listops=True)
+        res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
         self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0})
 
     def test_eq_folded(self):
+        _str = self._str
         jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i'])
-        global_s = "hello"
+        global_s = _str("hello")
         def f(n, b, s):
             if b:
-                s += "ello"
+                s += _str("ello")
             else:
-                s += "allo"
+                s += _str("allo")
             i = 0
             while n > 0:
                 jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -40,31 +44,18 @@
                 n -= 1 + (s == global_s)
                 i += 1
             return i
-        res = self.meta_interp(f, [10, True, 'h'], listops=True)
+        res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
         self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0})
 
     def test_newstr(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
         def f(n, m):
             while True:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                bytecode = 'adlfkj' + chr(n)
-                res = bytecode[n]
-                m -= 1
-                if m < 0:
-                    return ord(res)
-        res = self.meta_interp(f, [6, 10])
-        assert res == 6
-
-    def test_newunicode(self):
-        jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
-        def f(n, m):
-            while True:
-                jitdriver.can_enter_jit(m=m, n=n)
-                jitdriver.jit_merge_point(m=m, n=n)
-                bytecode = u'adlfkj' + unichr(n)
+                bytecode = _str('adlfkj') + _chr(n)
                 res = bytecode[n]
                 m -= 1
                 if m < 0:
@@ -73,95 +64,96 @@
         assert res == 6
 
     def test_char2string_pure(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n):
-                while n > 0:
-                    jitdriver.can_enter_jit(n=n)
-                    jitdriver.jit_merge_point(n=n)
-                    s = dochr(n)
-                    if not we_are_jitted():
-                        s += s     # forces to be a string
-                    if n > 100:
-                        escape(s)
-                    n -= 1
-                return 42
-            self.meta_interp(f, [6])
-            self.check_loops(newstr=0, strsetitem=0, strlen=0,
-                             newunicode=0, unicodesetitem=0, unicodelen=0)
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n):
+            while n > 0:
+                jitdriver.can_enter_jit(n=n)
+                jitdriver.jit_merge_point(n=n)
+                s = _chr(n)
+                if not we_are_jitted():
+                    s += s     # forces to be a string
+                if n > 100:
+                    escape(s)
+                n -= 1
+            return 42
+        self.meta_interp(f, [6])
+        self.check_loops(newstr=0, strsetitem=0, strlen=0,
+                         newunicode=0, unicodesetitem=0, unicodelen=0)
 
     def test_char2string_escape(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['n', 'total'])
-            @dont_look_inside
-            def escape(x):
-                return ord(x[0])
-            def f(n):
-                total = 0
-                while n > 0:
-                    jitdriver.can_enter_jit(n=n, total=total)
-                    jitdriver.jit_merge_point(n=n, total=total)
-                    s = dochr(n)
-                    if not we_are_jitted():
-                        s += s    # forces to be a string
-                    total += escape(s)
-                    n -= 1
-                return total
-            res = self.meta_interp(f, [6])
-            assert res == 21
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['n', 'total'])
+        @dont_look_inside
+        def escape(x):
+            return ord(x[0])
+        def f(n):
+            total = 0
+            while n > 0:
+                jitdriver.can_enter_jit(n=n, total=total)
+                jitdriver.jit_merge_point(n=n, total=total)
+                s = _chr(n)
+                if not we_are_jitted():
+                    s += s    # forces to be a string
+                total += escape(s)
+                n -= 1
+            return total
+        res = self.meta_interp(f, [6])
+        assert res == 21
 
     def test_char2string2char(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
-            def f(m):
-                total = 0
-                while m > 0:
-                    jitdriver.can_enter_jit(m=m, total=total)
-                    jitdriver.jit_merge_point(m=m, total=total)
-                    string = dochr(m)
-                    if m > 100:
-                        string += string    # forces to be a string
-                    # read back the character
-                    c = string[0]
-                    total += ord(c)
-                    m -= 1
-                return total
-            res = self.meta_interp(f, [6])
-            assert res == 21
-            self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
-                             newunicode=0, unicodegetitem=0, unicodesetitem=0,
-                             unicodelen=0)
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
+        def f(m):
+            total = 0
+            while m > 0:
+                jitdriver.can_enter_jit(m=m, total=total)
+                jitdriver.jit_merge_point(m=m, total=total)
+                string = _chr(m)
+                if m > 100:
+                    string += string    # forces to be a string
+                # read back the character
+                c = string[0]
+                total += ord(c)
+                m -= 1
+            return total
+        res = self.meta_interp(f, [6])
+        assert res == 21
+        self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
+                         newunicode=0, unicodegetitem=0, unicodesetitem=0,
+                         unicodelen=0)
 
     def test_strconcat_pure(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            mylist = [somestr+str(i) for i in range(10)]
-            def f(n, m):
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = mylist[n] + mylist[m]
-                    if m > 100:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 7])
-            self.check_loops(newstr=0, strsetitem=0,
-                             newunicode=0, unicodesetitem=0,
-                             call=0, call_pure=0)
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        mylist = [_str("abc") + _str(i) for i in range(10)]
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = mylist[n] + mylist[m]
+                if m > 100:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(newstr=0, strsetitem=0,
+                         newunicode=0, unicodesetitem=0,
+                         call=0, call_pure=0)
 
     def test_strconcat_escape_str_str(self):
+        _str = self._str
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
@@ -171,46 +163,64 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=0,
+                             copyunicodecontent=2,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_str_char(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = mylist[n] + chr(m)
+                s = mylist[n] + _chr(m)
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=1,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_char_str(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = chr(n) + mylist[m]
+                s = _chr(n) + mylist[m]
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=1,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_char_char(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
@@ -219,91 +229,132 @@
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = chr(n) + chr(m)
+                s = _chr(n) + _chr(m)
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=2,
+                             copyunicodecontent=0,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_str_char_str(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = mylist[n] + chr(n) + mylist[m]
+                s = mylist[n] + _chr(n) + mylist[m]
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=2,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_guard_fail(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            mylist = [somestr+str(i) for i in range(12)]
-            def f(n, m):
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = mylist[n] + mylist[m]
-                    if m & 1:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 10])
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        mylist = [_str("abc") + _str(i) for i in range(12)]
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = mylist[n] + mylist[m]
+                if m & 1:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 10])
 
     def test_strslice(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n, m):
-                assert n >= 0
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = "foobarbazetc"[m:n]
-                    if m <= 5:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [10, 10])
+        _str = self._str
+        longstring = _str("foobarbazetc")
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n, m):
+            assert n >= 0
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = longstring[m:n]
+                if m <= 5:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [10, 10])
 
     def test_streq_char(self):
-        for somestr in ["?abcdefg", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n, m):
-                assert n >= 0
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = somestr[:m]
-                    escape(s == "?")
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 7])
-            self.check_loops(newstr=0, newunicode=0)
-
-
-class TestOOtype(StringTests, OOJitMixin):
-    CALL = "oosend"
-    CALL_PURE = "oosend_pure"
+        _str = self._str
+        longstring = _str("?abcdefg")
+        somechar = _str("?")
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n, m):
+            assert n >= 0
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = longstring[:m]
+                escape(s == somechar)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(newstr=0, newunicode=0)
+
+
+#class TestOOtype(StringTests, OOJitMixin):
+#    CALL = "oosend"
+#    CALL_PURE = "oosend_pure"
 
 class TestLLtype(StringTests, LLJitMixin):
     CALL = "call"
     CALL_PURE = "call_pure"
+
+class TestLLtypeUnicode(TestLLtype):
+    _str, _chr = unicode, unichr
+
+    def test_str2unicode(self):
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        class Foo:
+            pass
+        @dont_look_inside
+        def escape(x):
+            assert x == _str("6y")
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                foo = Foo()
+                foo.y = chr(m)
+                foo.y = "y"
+                s = _str(str(n)) + _str(foo.y)
+                escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(call=3,    # str(), _str(), escape()
+                         newunicode=1, unicodegetitem=0,
+                         unicodesetitem=1, copyunicodecontent=1)

Modified: pypy/branch/32ptr-on-64bit/pypy/jit/tl/spli/interpreter.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/jit/tl/spli/interpreter.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/jit/tl/spli/interpreter.py	Tue Oct 12 14:42:59 2010
@@ -1,12 +1,14 @@
 import os
-from pypy.tool import stdlib_opcode as opcode
+from pypy.tool import stdlib_opcode
 from pypy.jit.tl.spli import objects, pycode
-from pypy.tool.stdlib_opcode import unrolling_opcode_descs
-from pypy.tool.stdlib_opcode import opcode_method_names
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import JitDriver, hint, dont_look_inside
 from pypy.rlib.objectmodel import we_are_translated
 
+opcode_method_names = stdlib_opcode.host_bytecode_spec.method_names
+unrolling_opcode_descs = unrolling_iterable(
+    stdlib_opcode.host_bytecode_spec.ordered_opdescs)
+HAVE_ARGUMENT = stdlib_opcode.host_HAVE_ARGUMENT
 
 compare_ops = [
     "cmp_lt",   # "<"
@@ -79,7 +81,7 @@
             self.stack_depth = hint(self.stack_depth, promote=True)
             op = ord(code[instr_index])
             instr_index += 1
-            if op >= opcode.HAVE_ARGUMENT:
+            if op >= HAVE_ARGUMENT:
                 low = ord(code[instr_index])
                 hi = ord(code[instr_index + 1])
                 oparg = (hi << 8) | low
@@ -183,6 +185,12 @@
             next_instr += arg
         return next_instr
 
+    def POP_JUMP_IF_FALSE(self, arg, next_instr, code):
+        w_cond = self.pop()
+        if not w_cond.is_true():
+            next_instr = arg
+        return next_instr
+
     def JUMP_FORWARD(self, arg, next_instr, code):
         return next_instr + arg
 

Modified: pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/interp_classobj.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/interp_classobj.py	Tue Oct 12 14:42:59 2010
@@ -2,9 +2,11 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, applevel
 from pypy.interpreter.gateway import interp2app, ObjSpace
-from pypy.interpreter.typedef import TypeDef, make_weakref_descr
+from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import GetSetProperty, descr_get_dict
+from pypy.interpreter.typedef import descr_set_dict
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.objectmodel import compute_identity_hash
 from pypy.rlib.debug import make_sure_not_resized
@@ -57,6 +59,14 @@
         self.bases_w = bases
         self.w_dict = w_dict
  
+    def instantiate(self, space):
+        cache = space.fromcache(Cache)
+        if self.lookup(space, '__del__') is not None:
+            w_inst = cache.cls_with_del(space, self)
+        else:
+            w_inst = cache.cls_without_del(space, self)
+        return w_inst
+
     def getdict(self):
         return self.w_dict
 
@@ -100,15 +110,15 @@
         return False
 
     @jit.unroll_safe
-    def lookup(self, space, w_attr):
+    def lookup(self, space, attr):
         # returns w_value or interplevel None
-        w_result = space.finditem(self.w_dict, w_attr)
+        w_result = space.finditem_str(self.w_dict, attr)
         if w_result is not None:
             return w_result
         for base in self.bases_w:
             # XXX fix annotation of bases_w to be a list of W_ClassObjects
             assert isinstance(base, W_ClassObject)
-            w_result = base.lookup(space, w_attr)
+            w_result = base.lookup(space, attr)
             if w_result is not None:
                 return w_result
         return None
@@ -122,7 +132,7 @@
                 return space.wrap(self.name)
             elif name == "__bases__":
                 return space.newtuple(self.bases_w)
-        w_value = self.lookup(space, w_attr)
+        w_value = self.lookup(space, name)
         if w_value is None:
             raise operationerrfmt(
                 space.w_AttributeError,
@@ -147,7 +157,7 @@
                 self.setbases(space, w_value)
                 return
             elif name == "__del__":
-                if self.lookup(space, w_attr) is None:
+                if self.lookup(space, name) is None:
                     msg = ("a __del__ method added to an existing class "
                            "will not be called")
                     space.warn(msg, space.w_RuntimeWarning)
@@ -195,13 +205,20 @@
         # NOT_RPYTHON
         return '<W_ClassObject(%s)>' % self.name
 
+class Cache:
+    def __init__(self, space):
+        from pypy.interpreter.typedef import _usersubclswithfeature
+        # evil
+        self.cls_without_del = _usersubclswithfeature(
+                space.config, W_InstanceObject, "dict", "weakref")
+        self.cls_with_del = _usersubclswithfeature(
+                space.config, self.cls_without_del, "del")
+
+
 def class_descr_call(space, w_self, __args__):
     self = space.interp_w(W_ClassObject, w_self)
-    if self.lookup(space, space.wrap('__del__')) is not None:
-        w_inst = W_InstanceObjectWithDel(space, self)
-    else:
-        w_inst = W_InstanceObject(space, self)
-    w_init = w_inst.getattr_from_class(space, space.wrap('__init__'))
+    w_inst = self.instantiate(space)
+    w_init = w_inst.getattr_from_class(space, '__init__')
     if w_init is not None:
         w_result = space.call_args(w_init, __args__)
         if not space.is_w(w_result, space.w_None):
@@ -234,7 +251,7 @@
 
 def make_unary_instance_method(name):
     def unaryop(self, space):
-        w_meth = self.getattr(space, space.wrap(name), True)
+        w_meth = self.getattr(space, name, True)
         return space.call_function(w_meth)
     unaryop.func_name = name
     return unaryop
@@ -242,7 +259,7 @@
 def make_binary_returning_notimplemented_instance_method(name):
     def binaryop(self, space, w_other):
         try:
-            w_meth = self.getattr(space, space.wrap(name), False)
+            w_meth = self.getattr(space, name, False)
         except OperationError, e:
             if e.match(space, space.w_AttributeError):
                 return space.w_NotImplemented
@@ -267,7 +284,7 @@
             w_a = self
             w_b = w_other
         if w_a is self:
-            w_meth = self.getattr(space, space.wrap(specialname), False)
+            w_meth = self.getattr(space, specialname, False)
             if w_meth is None:
                 return space.w_NotImplemented
             return space.call_function(w_meth, w_b)
@@ -278,7 +295,7 @@
     def rbinaryop(self, space, w_other):
         w_a, w_b = _coerce_helper(space, self, w_other)
         if w_a is None or w_a is self:
-            w_meth = self.getattr(space, space.wrap(rspecialname), False)
+            w_meth = self.getattr(space, rspecialname, False)
             if w_meth is None:
                 return space.w_NotImplemented
             return space.call_function(w_meth, w_other)
@@ -302,46 +319,34 @@
         raise OperationError(
             space.w_TypeError,
             space.wrap("instance() first arg must be class"))
-    if space.is_w(w_dict, space.w_None):
-        w_dict = None
-    elif not space.is_true(space.isinstance(w_dict, space.w_dict)):
-        raise OperationError(
-            space.w_TypeError,
-            space.wrap("instance() second arg must be dictionary or None"))
-    return W_InstanceObject(space, w_class, w_dict)
+    w_result = w_class.instantiate(space)
+    if not space.is_w(w_dict, space.w_None):
+        w_result.setdict(space, w_dict)
+    return w_result
 
 class W_InstanceObject(Wrappable):
-    def __init__(self, space, w_class, w_dict=None):
-        if w_dict is None:
-            w_dict = space.newdict(instance=True)
+    def __init__(self, space, w_class):
+        # note that user_setup is overridden by the typedef.py machinery
+        self.user_setup(space, space.gettypeobject(self.typedef))
         assert isinstance(w_class, W_ClassObject)
         self.w_class = w_class
-        self.w_dict = w_dict
-        self.space = space
-
-    def getdict(self):
-        return self.w_dict
 
-    def setdict(self, space, w_dict):
-        if (w_dict is None or
-            not space.is_true(space.isinstance(w_dict, space.w_dict))):
-            raise OperationError(
-                space.w_TypeError,
-                space.wrap("__dict__ must be a dictionary object"))
-        self.w_dict = w_dict
+    def user_setup(self, space, w_subtype):
+        self.space = space
 
-    def setclass(self, space, w_class):
+    def set_oldstyle_class(self, space, w_class):
         if w_class is None or not isinstance(w_class, W_ClassObject):
             raise OperationError(
                 space.w_TypeError,
                 space.wrap("__class__ must be set to a class"))
         self.w_class = w_class
 
-    def getattr_from_class(self, space, w_name):
+    def getattr_from_class(self, space, name):
         # Look up w_name in the class dict, and call its __get__.
         # This method ignores the instance dict and the __getattr__.
         # Returns None if not found.
-        w_value = self.w_class.lookup(space, w_name)
+        assert isinstance(name, str)
+        w_value = self.w_class.lookup(space, name)
         if w_value is None:
             return None
         w_descr_get = space.lookup(w_value, '__get__')
@@ -349,19 +354,20 @@
             return w_value
         return space.call_function(w_descr_get, w_value, self, self.w_class)
 
-    def getattr(self, space, w_name, exc=True):
+    def getattr(self, space, name, exc=True):
         # Normal getattr rules: look up w_name in the instance dict,
         # in the class dict, and then via a call to __getatttr__.
-        w_result = space.finditem(self.w_dict, w_name)
+        assert isinstance(name, str)
+        w_result = self.getdictvalue(space, name)
         if w_result is not None:
             return w_result
-        w_result = self.getattr_from_class(space, w_name)
+        w_result = self.getattr_from_class(space, name)
         if w_result is not None:
             return w_result
-        w_meth = self.getattr_from_class(space, space.wrap('__getattr__'))
+        w_meth = self.getattr_from_class(space, '__getattr__')
         if w_meth is not None:
             try:
-                return space.call_function(w_meth, w_name)
+                return space.call_function(w_meth, space.wrap(name))
             except OperationError, e:
                 if not exc and e.match(space, space.w_AttributeError):
                     return None     # eat the AttributeError
@@ -371,7 +377,7 @@
             raise operationerrfmt(
                 space.w_AttributeError,
                 "%s instance has no attribute '%s'",
-                self.w_class.name, space.str_w(w_name))
+                self.w_class.name, name)
         else:
             return None
 
@@ -379,44 +385,46 @@
         name = space.str_w(w_attr)
         if len(name) >= 8 and name[0] == '_':
             if name == "__dict__":
-                return self.w_dict
+                return self.getdict()
             elif name == "__class__":
                 return self.w_class
-        return self.getattr(space, w_attr)
+        return self.getattr(space, name)
 
     def descr_setattr(self, space, w_name, w_value):
         name = unwrap_attr(space, w_name)
-        w_meth = self.getattr_from_class(space, space.wrap('__setattr__'))
+        w_meth = self.getattr_from_class(space, '__setattr__')
         if name and name[0] == "_":
             if name == '__dict__':
                 self.setdict(space, w_value)
                 return
             if name == '__class__':
-                self.setclass(space, w_value)
+                self.set_oldstyle_class(space, w_value)
                 return
             if name == '__del__' and w_meth is None:
-                if (not isinstance(self, W_InstanceObjectWithDel)
-                    and space.finditem(self.w_dict, w_name) is None):
+                cache = space.fromcache(Cache)
+                if (not isinstance(self, cache.cls_with_del)
+                    and self.getdictvalue(space, '__del__') is None):
                     msg = ("a __del__ method added to an instance "
                            "with no __del__ in the class will not be called")
                     space.warn(msg, space.w_RuntimeWarning)
         if w_meth is not None:
             space.call_function(w_meth, w_name, w_value)
         else:
-            self.setdictvalue(space, name, w_value)
+            # bit obscure: appease normalization
+            self.setdictvalue(space, name, w_value, True)
 
     def descr_delattr(self, space, w_name):
         name = unwrap_attr(space, w_name)
         if name and name[0] == "_":
             if name == '__dict__':
                 # use setdict to raise the error
-                self.setdict(space, None)
+                self.setdict(space, space.w_None)
                 return
             elif name == '__class__':
-                # use setclass to raise the error
-                self.setclass(space, None)
+                # use set_oldstyle_class to raise the error
+                self.set_oldstyle_class(space, None)
                 return
-        w_meth = self.getattr_from_class(space, space.wrap('__delattr__'))
+        w_meth = self.getattr_from_class(space, '__delattr__')
         if w_meth is not None:
             space.call_function(w_meth, w_name)
         else:
@@ -427,7 +435,7 @@
                     self.w_class.name, name)
 
     def descr_repr(self, space):
-        w_meth = self.getattr(space, space.wrap('__repr__'), False)
+        w_meth = self.getattr(space, '__repr__', False)
         if w_meth is None:
             w_class = self.w_class
             mod = w_class.get_module_string(space)
@@ -435,19 +443,19 @@
         return space.call_function(w_meth)
 
     def descr_str(self, space):
-        w_meth = self.getattr(space, space.wrap('__str__'), False)
+        w_meth = self.getattr(space, '__str__', False)
         if w_meth is None:
             return self.descr_repr(space)
         return space.call_function(w_meth)
 
     def descr_unicode(self, space):
-        w_meth = self.getattr(space, space.wrap('__unicode__'), False)
+        w_meth = self.getattr(space, '__unicode__', False)
         if w_meth is None:
             return self.descr_str(space)
         return space.call_function(w_meth)
 
     def descr_len(self, space):
-        w_meth = self.getattr(space, space.wrap('__len__'))
+        w_meth = self.getattr(space, '__len__')
         w_result = space.call_function(w_meth)
         if space.is_true(space.isinstance(w_result, space.w_int)):
             if space.is_true(space.lt(w_result, space.wrap(0))):
@@ -460,22 +468,22 @@
             space.wrap("__len__() should return an int"))
 
     def descr_getitem(self, space, w_key):
-        w_meth = self.getattr(space, space.wrap('__getitem__'))
+        w_meth = self.getattr(space, '__getitem__')
         return space.call_function(w_meth, w_key)
 
     def descr_setitem(self, space, w_key, w_value):
-        w_meth = self.getattr(space, space.wrap('__setitem__'))
+        w_meth = self.getattr(space, '__setitem__')
         space.call_function(w_meth, w_key, w_value)
 
     def descr_delitem(self, space, w_key):
-        w_meth = self.getattr(space, space.wrap('__delitem__'))
+        w_meth = self.getattr(space, '__delitem__')
         space.call_function(w_meth, w_key)
 
     def descr_iter(self, space):
-        w_meth = self.getattr(space, space.wrap('__iter__'), False)
+        w_meth = self.getattr(space, '__iter__', False)
         if w_meth is not None:
             return space.call_function(w_meth)
-        w_meth = self.getattr(space, space.wrap('__getitem__'), False)
+        w_meth = self.getattr(space, '__getitem__', False)
         if w_meth is None:
             raise OperationError(
                 space.w_TypeError,
@@ -485,14 +493,14 @@
     # don't see the point
 
     def descr_getslice(self, space, w_i, w_j):
-        w_meth = self.getattr(space, space.wrap('__getslice__'), False)
+        w_meth = self.getattr(space, '__getslice__', False)
         if w_meth is not None:
             return space.call_function(w_meth, w_i, w_j)
         else:
             return space.getitem(self, space.newslice(w_i, w_j, space.w_None))
 
     def descr_setslice(self, space, w_i, w_j, w_sequence):
-        w_meth = self.getattr(space, space.wrap('__setslice__'), False)
+        w_meth = self.getattr(space, '__setslice__', False)
         if w_meth is not None:
             space.call_function(w_meth, w_i, w_j, w_sequence)
         else:
@@ -500,20 +508,20 @@
                           w_sequence)
 
     def descr_delslice(self, space, w_i, w_j):
-        w_meth = self.getattr(space, space.wrap('__delslice__'), False)
+        w_meth = self.getattr(space, '__delslice__', False)
         if w_meth is not None:
             space.call_function(w_meth, w_i, w_j)
         else:
             return space.delitem(self, space.newslice(w_i, w_j, space.w_None))
 
     def descr_call(self, space, __args__):
-        w_meth = self.getattr(space, space.wrap('__call__'))
+        w_meth = self.getattr(space, '__call__')
         return space.call_args(w_meth, __args__)
 
     def descr_nonzero(self, space):
-        w_func = self.getattr(space, space.wrap('__nonzero__'), False)
+        w_func = self.getattr(space, '__nonzero__', False)
         if w_func is None:
-            w_func = self.getattr(space, space.wrap('__len__'), False)
+            w_func = self.getattr(space, '__len__', False)
             if w_func is None:
                 return space.w_True
         w_result = space.call_function(w_func)
@@ -537,7 +545,7 @@
                 not isinstance(w_b, W_InstanceObject)):
                 return space.cmp(w_a, w_b)
         if isinstance(w_a, W_InstanceObject):
-            w_func = w_a.getattr(space, space.wrap('__cmp__'), False)
+            w_func = w_a.getattr(space, '__cmp__', False)
             if w_func is not None:
                 w_res = space.call_function(w_func, w_b)
                 if space.is_w(w_res, space.w_NotImplemented):
@@ -556,7 +564,7 @@
                     return space.wrap(-1)
                 return space.wrap(0)
         if isinstance(w_b, W_InstanceObject):
-            w_func = w_b.getattr(space, space.wrap('__cmp__'), False)
+            w_func = w_b.getattr(space, '__cmp__', False)
             if w_func is not None:
                 w_res = space.call_function(w_func, w_a)
                 if space.is_w(w_res, space.w_NotImplemented):
@@ -577,10 +585,10 @@
         return space.w_NotImplemented
 
     def descr_hash(self, space):
-        w_func = self.getattr(space, space.wrap('__hash__'), False)
+        w_func = self.getattr(space, '__hash__', False)
         if w_func is None:
-            w_eq =  self.getattr(space, space.wrap('__eq__'), False)
-            w_cmp =  self.getattr(space, space.wrap('__cmp__'), False)
+            w_eq =  self.getattr(space, '__eq__', False)
+            w_cmp =  self.getattr(space, '__cmp__', False)
             if w_eq is not None or w_cmp is not None:
                 raise OperationError(space.w_TypeError,
                                      space.wrap("unhashable instance"))
@@ -595,7 +603,7 @@
         return w_ret
 
     def descr_index(self, space):
-        w_func = self.getattr(space, space.wrap('__index__'), False)
+        w_func = self.getattr(space, '__index__', False)
         if w_func is not None:
             return space.call_function(w_func)
         raise OperationError(
@@ -603,7 +611,7 @@
             space.wrap("object cannot be interpreted as an index"))
 
     def descr_contains(self, space, w_obj):
-        w_func = self.getattr(space, space.wrap('__contains__'), False)
+        w_func = self.getattr(space, '__contains__', False)
         if w_func is not None:
             return space.wrap(space.is_true(space.call_function(w_func, w_obj)))
         # now do it ourselves
@@ -626,7 +634,7 @@
                 w_a = self
                 w_b = w_other
             if w_a is self:
-                w_func = self.getattr(space, space.wrap('__pow__'), False)
+                w_func = self.getattr(space, '__pow__', False)
                 if w_func is not None:
                     return space.call_function(w_func, w_other)
                 return space.w_NotImplemented
@@ -634,7 +642,7 @@
                 return space.pow(w_a, w_b, space.w_None)
         else:
             # CPython also doesn't try coercion in this case
-            w_func = self.getattr(space, space.wrap('__pow__'), False)
+            w_func = self.getattr(space, '__pow__', False)
             if w_func is not None:
                 return space.call_function(w_func, w_other, w_modulo)
             return space.w_NotImplemented
@@ -646,7 +654,7 @@
                 w_a = self
                 w_b = w_other
             if w_a is self:
-                w_func = self.getattr(space, space.wrap('__rpow__'), False)
+                w_func = self.getattr(space, '__rpow__', False)
                 if w_func is not None:
                     return space.call_function(w_func, w_other)
                 return space.w_NotImplemented
@@ -654,13 +662,13 @@
                 return space.pow(w_b, w_a, space.w_None)
         else:
             # CPython also doesn't try coercion in this case
-            w_func = self.getattr(space, space.wrap('__rpow__'), False)
+            w_func = self.getattr(space, '__rpow__', False)
             if w_func is not None:
                 return space.call_function(w_func, w_other, w_modulo)
             return space.w_NotImplemented
 
     def descr_next(self, space):
-        w_func = self.getattr(space, space.wrap('next'), False)
+        w_func = self.getattr(space, 'next', False)
         if w_func is None:
             raise OperationError(space.w_TypeError,
                                  space.wrap("instance has no next() method"))
@@ -669,10 +677,9 @@
     def descr_del(self, space):
         # Note that this is called from executioncontext.UserDelAction
         # via the space.userdel() method.
-        w_name = space.wrap('__del__')
-        w_func = space.finditem(self.w_dict, w_name)
+        w_func = self.getdictvalue(space, '__del__')
         if w_func is None:
-            w_func = self.getattr_from_class(space, w_name)
+            w_func = self.getattr_from_class(space, '__del__')
         if w_func is not None:
             space.call_function(w_func)
 
@@ -717,6 +724,14 @@
         rmeth,
         unwrap_spec=["self", ObjSpace, W_Root])
 
+
+def descr_del_dict(space, w_inst):
+    # use setdict to raise the error
+    w_inst.setdict(space, space.w_None)
+
+dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict)
+dict_descr.name = '__dict__'
+
 W_InstanceObject.typedef = TypeDef("instance",
     __new__ = interp2app(descr_instance_new),
     __getattribute__ = interp2app(W_InstanceObject.descr_getattribute,
@@ -766,12 +781,9 @@
                          unwrap_spec=['self', ObjSpace, W_Root, W_Root]),
     next = interp2app(W_InstanceObject.descr_next,
                       unwrap_spec=['self', ObjSpace]),
-    __weakref__ = make_weakref_descr(W_InstanceObject),
     __del__ = interp2app(W_InstanceObject.descr_del,
                          unwrap_spec=['self', ObjSpace]),
+    __dict__ = dict_descr,
     **rawdict
 )
-
-class W_InstanceObjectWithDel(W_InstanceObject):
-    def __del__(self):
-        self._enqueue_for_destruction(self.space)
+W_InstanceObject.typedef.acceptable_as_base_class = False

Modified: pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/test/test_classobj.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/__builtin__/test/test_classobj.py	Tue Oct 12 14:42:59 2010
@@ -928,6 +928,31 @@
         assert x is b
         assert y == 5
 
+    def test_cant_subclass_instance(self):
+        class A:
+            pass
+        try:
+            class B(type(A())):
+                pass
+        except TypeError:
+            pass
+        else:
+            assert 0, "should have raised"
+
+    def test_dict_descriptor(self):
+        import sys
+        if not hasattr(sys, 'pypy_objspaceclass'):
+            skip("on CPython old-style instances don't have a __dict__ descriptor")
+        class A:
+            pass
+        a = A()
+        a.x = 1
+        descr = type(a).__dict__['__dict__']
+        assert descr.__get__(a) == {'x': 1}
+        descr.__set__(a, {'x': 2})
+        assert a.x == 2
+        raises(TypeError, descr.__delete__, a)
+
 
 class AppTestOldStyleSharing(AppTestOldstyle):
     def setup_class(cls):
@@ -966,3 +991,22 @@
             a = 1
             b = 2
         assert self.is_strdict(A)
+
+class AppTestOldStyleMapDict(AppTestOldstyle):
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withmapdict": True})
+        if option.runappdirect:
+            py.test.skip("can only be run on py.py")
+        def has_mapdict(space, w_inst):
+            return space.wrap(w_inst._get_mapdict_map() is not None)
+        cls.w_has_mapdict = cls.space.wrap(gateway.interp2app(has_mapdict))
+
+
+    def test_has_mapdict(self):
+        class A:
+            def __init__(self):
+                self.x = 42
+        a = A()
+        assert a.x == 42
+        assert self.has_mapdict(a)
+

Modified: pypy/branch/32ptr-on-64bit/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/_weakref/interp__weakref.py	Tue Oct 12 14:42:59 2010
@@ -7,7 +7,7 @@
 import weakref
 
 
-class WeakrefLifeline(object):
+class WeakrefLifeline(W_Root):
     def __init__(self, space):
         self.space = space       # this is here for W_Root.clear_all_weakrefs()
         self.refs_weak = []

Modified: pypy/branch/32ptr-on-64bit/pypy/module/cpyext/classobject.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/cpyext/classobject.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/cpyext/classobject.py	Tue Oct 12 14:42:59 2010
@@ -15,16 +15,20 @@
     class is the class of new object.  The dict parameter will be used as the
     object's __dict__; if NULL, a new dictionary will be created for the
     instance."""
-    if not PyClass_Check(space, w_class):
+    if not isinstance(w_class, W_ClassObject):
         return PyErr_BadInternalCall(space)
-    return W_InstanceObject(space, w_class, w_dict)
+    w_result = w_class.instantiate(space)
+    if w_dict is not None:
+        w_result.setdict(space, w_dict)
+    return w_result
 
 @cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL)
 def _PyInstance_Lookup(space, w_instance, w_name):
+    name = space.str_w(w_name)
     assert isinstance(w_instance, W_InstanceObject)
-    w_result = space.finditem(w_instance.w_dict, w_name)
+    w_result = w_instance.getdictvalue(space, name)
     if w_result is not None:
         return w_result
-    return w_instance.w_class.lookup(space, w_name)
+    return w_instance.w_class.lookup(space, name)
 
 

Modified: pypy/branch/32ptr-on-64bit/pypy/module/gc/referents.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/gc/referents.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/gc/referents.py	Tue Oct 12 14:42:59 2010
@@ -15,6 +15,10 @@
 
 def try_cast_gcref_to_w_root(gcref):
     w_obj = rgc.try_cast_gcref_to_instance(W_Root, gcref)
+    # Ignore instances of exactly the class W_Root.  Seems that
+    # we get one on 64-bit translations, for some reason.
+    if w_obj is not None and type(w_obj) is W_Root:
+        w_obj = None
     if not we_are_translated() and not hasattr(w_obj, 'typedef'):
         w_obj = None
     return w_obj

Modified: pypy/branch/32ptr-on-64bit/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/pypyjit/test/test_pypy_c.py	Tue Oct 12 14:42:59 2010
@@ -272,7 +272,7 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 7
+        assert len(ops[0].get_opnames("guard")) <= 2
         assert not ops[1] # second LOOKUP_METHOD folded away
 
         ops = self.get_by_bytecode("CALL_METHOD")
@@ -283,7 +283,7 @@
             else:
                 assert not bytecode.get_opnames("call")
             assert not bytecode.get_opnames("new")
-            assert len(bytecode.get_opnames("guard")) <= 9
+            assert len(bytecode.get_opnames("guard")) <= 6
         assert len(ops[1]) < len(ops[0])
 
         ops = self.get_by_bytecode("LOAD_ATTR")
@@ -317,8 +317,8 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 7
-        assert len(ops[0].get_opnames("getfield")) < 6
+        assert len(ops[0].get_opnames("guard")) <= 2
+        assert len(ops[0].get_opnames("getfield")) < 5
         assert not ops[1] # second LOOKUP_METHOD folded away
 
     def test_default_and_kw(self):
@@ -382,7 +382,7 @@
                     a.x = 2
                     i = i + a.x
                 return i
-        ''', 67,
+        ''', 69,
                    ([20], 20),
                    ([31], 32))
 
@@ -390,7 +390,7 @@
                 self.get_by_bytecode("CALL_FUNCTION"))
         assert not callA.get_opnames("call")
         assert not callA.get_opnames("new")
-        assert len(callA.get_opnames("guard")) <= 8
+        assert len(callA.get_opnames("guard")) <= 2
         assert not callisinstance1.get_opnames("call")
         assert not callisinstance1.get_opnames("new")
         assert len(callisinstance1.get_opnames("guard")) <= 2
@@ -742,6 +742,8 @@
                     '''%(op1, float(a)/4.0, float(b)/4.0, op2), 109, ([], res))
 
     def test_boolrewrite_ptr(self):
+        # XXX this test is way too imprecise in what it is actually testing
+        # it should count the number of guards instead
         compares = ('a == b', 'b == a', 'a != b', 'b != a', 'a == c', 'c != b')
         for e1 in compares:
             for e2 in compares:
@@ -765,7 +767,7 @@
                 print
                 print 'Test:', e1, e2, n, res
                 self.run_source('''
-                class tst:
+                class tst(object):
                     pass
                 def main():
                     a = tst()
@@ -847,6 +849,8 @@
             ''', 65, ([], 122880))
 
     def test_array_intimg(self):
+        # XXX this test is way too imprecise in what it is actually testing
+        # it should count the number of guards instead
         for tc, maxops in zip('ilILd', (67, 67, 69, 69, 61)):
             res = 73574560
             if tc in 'IL':

Modified: pypy/branch/32ptr-on-64bit/pypy/module/signal/interp_signal.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/signal/interp_signal.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/signal/interp_signal.py	Tue Oct 12 14:42:59 2010
@@ -1,7 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import W_Root, ObjSpace
 from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.rlib.rarithmetic import LONG_BIT, intmask
 import signal as cpy_signal
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -64,8 +63,8 @@
 class CheckSignalAction(AsyncAction):
     """An action that is automatically invoked when a signal is received."""
 
-    # The C-level signal handler sets the highest bit of pypysig_occurred:
-    bitmask = intmask(1 << (LONG_BIT-1))
+    # The C-level signal handler sets the bit 30 of pypysig_occurred:
+    bitmask = 1 << 30
 
     def __init__(self, space):
         AsyncAction.__init__(self, space)

Modified: pypy/branch/32ptr-on-64bit/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/sys/__init__.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/sys/__init__.py	Tue Oct 12 14:42:59 2010
@@ -7,13 +7,15 @@
     """Sys Builtin Module. """
     def __init__(self, space, w_name):
         """NOT_RPYTHON""" # because parent __init__ isn't
+        if space.config.translating:
+            del self.__class__.interpleveldefs['pypy_getudir']
         super(Module, self).__init__(space, w_name) 
         self.checkinterval = 100
         self.recursionlimit = 100
         self.w_default_encoder = None
         self.defaultencoding = "ascii"
         self.filesystemencoding = None
-        
+
     interpleveldefs = {
         '__name__'              : '(space.wrap("sys"))', 
         '__doc__'               : '(space.wrap("PyPy sys module"))', 
@@ -37,7 +39,7 @@
         'argv'                  : 'state.get(space).w_argv', 
         'warnoptions'           : 'state.get(space).w_warnoptions', 
         'builtin_module_names'  : 'state.w_None',
-        'pypy_getudir'          : 'state.pypy_getudir', 
+        'pypy_getudir'          : 'state.pypy_getudir',    # not translated
         'pypy_initial_path'     : 'state.pypy_initial_path',
 
         '_getframe'             : 'vm._getframe', 

Modified: pypy/branch/32ptr-on-64bit/pypy/module/sys/state.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/module/sys/state.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/module/sys/state.py	Tue Oct 12 14:42:59 2010
@@ -95,15 +95,8 @@
 def getio(space):
     return space.fromcache(IOState)
 
-def _pypy_getudir(space):
-    """NOT_RPYTHON"""
+def pypy_getudir(space):
+    """NOT_RPYTHON
+    (should be removed from interpleveldefs before translation)"""
     from pypy.tool.udir import udir
     return space.wrap(str(udir))
-_pypy_getudir._annspecialcase_ = "override:ignore"
-
-# we need the indirection because this function will live in a dictionary with other 
-# RPYTHON functions and share call sites with them. Better it not be a special-case
-# directly. 
-def pypy_getudir(space):
-    return _pypy_getudir(space)
-

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/celldict.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/celldict.py	Tue Oct 12 14:42:59 2010
@@ -45,7 +45,7 @@
         if space.is_w(space.type(w_key), space.w_str):
             self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
     def impl_setitem_str(self, name, w_value, shadows_type=True):
         self.getcell(name, True).w_value = w_value
@@ -66,7 +66,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
         
     def impl_length(self):
         # inefficient, but do we care?
@@ -85,7 +85,7 @@
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().getitem(w_lookup)
+            return self._as_rdict().impl_fallback_getitem(w_lookup)
 
     def impl_getitem_str(self, lookup):
         res = self.getcell(lookup, False)

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/dictmultiobject.py	Tue Oct 12 14:42:59 2010
@@ -102,17 +102,17 @@
         else:
             return None
 
-    # _________________________________________________________________ 
+    # _________________________________________________________________
     # implementation methods
     def impl_getitem(self, w_key):
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def impl_getitem_str(self, w_key):
+    def impl_getitem_str(self, key):
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def impl_setitem_str(self,  key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
         raise NotImplementedError("abstract base class")
 
     def impl_setitem(self,  w_key, w_value):
@@ -120,7 +120,7 @@
 
     def impl_delitem(self, w_key):
         raise NotImplementedError("abstract base class")
- 
+
     def impl_length(self):
         raise NotImplementedError("abstract base class")
 
@@ -310,7 +310,7 @@
         if space.is_w(space.type(w_key), space.w_str):
             self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
     def impl_setitem_str(self, key, w_value, shadows_type=True):
         self.content[key] = w_value
@@ -324,7 +324,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
         
     def impl_length(self):
         return len(self.content)
@@ -344,7 +344,7 @@
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().getitem(w_key)
+            return self._as_rdict().impl_fallback_getitem(w_key)
 
     def impl_iter(self):
         return StrIteratorImplementation(self.space, self)
@@ -414,7 +414,7 @@
             StrDictImplementation.impl_setitem_str(
                 self, self.space.str_w(w_key), w_value, False)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
     def impl_shadows_anything(self):
         return (self._shadows_anything or 
@@ -446,7 +446,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
 
     def impl_get_builtin_indexed(self, i):
         return self.shadowed[i]

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/fake.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/fake.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/fake.py	Tue Oct 12 14:42:59 2010
@@ -21,7 +21,6 @@
     #debug_print("faking obj %s" % x)
     ft = fake_type(type(x))
     return ft(space, x)
-fake_object._annspecialcase_ = "override:fake_object"
 
 import sys
 
@@ -47,7 +46,6 @@
         w_exc = space.wrap(exc)
         w_value = space.wrap(value)
     raise OperationError, OperationError(w_exc, w_value), tb
-wrap_exception._annspecialcase_ = "override:ignore"
 
 def fake_type(cpy_type):
     assert type(cpy_type) is type

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/model.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/model.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/model.py	Tue Oct 12 14:42:59 2010
@@ -18,6 +18,7 @@
     "withsmallint"   : ["smallintobject.W_SmallIntObject"],
     "withstrslice"   : ["strsliceobject.W_StringSliceObject"],
     "withstrjoin"    : ["strjoinobject.W_StringJoinObject"],
+    "withstrbuf"     : ["strbufobject.W_StringBufferObject"],
     "withrope"       : ["ropeobject.W_RopeObject",
                         "ropeobject.W_RopeIterObject"],
     "withropeunicode": ["ropeunicodeobject.W_RopeUnicodeObject",
@@ -75,6 +76,7 @@
         from pypy.objspace.std import ropeunicodeobject
         from pypy.objspace.std import strsliceobject
         from pypy.objspace.std import strjoinobject
+        from pypy.objspace.std import strbufobject
         from pypy.objspace.std import typeobject
         from pypy.objspace.std import sliceobject
         from pypy.objspace.std import longobject
@@ -222,6 +224,13 @@
                 (unicodeobject.W_UnicodeObject,
                                        strjoinobject.delegate_join2unicode)
                 ]
+        elif config.objspace.std.withstrbuf:
+            self.typeorder[strbufobject.W_StringBufferObject] += [
+                (stringobject.W_StringObject,
+                                       strbufobject.delegate_buf2str),
+                (unicodeobject.W_UnicodeObject,
+                                       strbufobject.delegate_buf2unicode)
+                ]
         if config.objspace.std.withrangelist:
             self.typeorder[rangeobject.W_RangeListObject] += [
                 (listobject.W_ListObject,

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/objspace.py	Tue Oct 12 14:42:59 2010
@@ -23,6 +23,7 @@
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.ropeobject import W_RopeObject
 from pypy.objspace.std.iterobject import W_SeqIterObject
 from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
@@ -242,7 +243,6 @@
             w_result = getattr(self, 'w_' + x.__name__)
             return w_result
         return None
-    wrap_exception_cls._annspecialcase_ = "override:wrap_exception_cls"
 
     def unwrap(self, w_obj):
         if isinstance(w_obj, Wrappable):
@@ -318,9 +318,14 @@
             w_subtype = w_type.check_user_subclass(w_subtype)
             if cls.typedef.applevel_subclasses_base is not None:
                 cls = cls.typedef.applevel_subclasses_base
-            subcls = get_unique_interplevel_subclass(
-                    self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
-                    w_subtype.needsdel, w_subtype.weakrefable)
+            if (self.config.objspace.std.withmapdict and cls is W_ObjectObject
+                    and not w_subtype.needsdel):
+                from pypy.objspace.std.mapdict import get_subclass_of_correct_size
+                subcls = get_subclass_of_correct_size(self, cls, w_subtype)
+            else:
+                subcls = get_unique_interplevel_subclass(
+                        self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
+                        w_subtype.needsdel, w_subtype.weakrefable)
             instance = instantiate(subcls)
             assert isinstance(instance, cls)
             instance.user_setup(self, w_subtype)

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/sharingdict.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/sharingdict.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/sharingdict.py	Tue Oct 12 14:42:59 2010
@@ -71,7 +71,7 @@
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().getitem(w_lookup)
+            return self._as_rdict().impl_fallback_getitem(w_lookup)
 
     def impl_getitem_str(self, lookup):
         i = self.structure.lookup_position(lookup)
@@ -84,7 +84,7 @@
         if space.is_w(space.type(w_key), space.w_str):
             self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
     @unroll_safe
     def impl_setitem_str(self, key, w_value, shadows_type=True):
@@ -132,7 +132,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
         
     def impl_length(self):
         return self.structure.length

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringobject.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringobject.py	Tue Oct 12 14:42:59 2010
@@ -14,7 +14,7 @@
 from pypy.rlib.rstring import StringBuilder, string_repeat
 from pypy.interpreter.buffer import StringBuffer
 
-from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \
+from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
      stringendswith, stringstartswith, joined2
 
 from pypy.objspace.std.formatting import mod_format

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringtype.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/stringtype.py	Tue Oct 12 14:42:59 2010
@@ -55,19 +55,14 @@
             return W_StringSliceObject(s, start, stop)
     return wrapstr(space, s[start:stop])
 
-def joined(space, strlist):
-    assert not space.config.objspace.std.withrope
-    if space.config.objspace.std.withstrjoin:
-        from pypy.objspace.std.strjoinobject import W_StringJoinObject
-        return W_StringJoinObject(strlist)
-    else:
-        return wrapstr(space, "".join(strlist))
-
 def joined2(space, str1, str2):
     assert not space.config.objspace.std.withrope
     if space.config.objspace.std.withstrjoin:
         from pypy.objspace.std.strjoinobject import W_StringJoinObject
         return W_StringJoinObject([str1, str2])
+    elif space.config.objspace.std.withstrbuf:
+        from pypy.objspace.std.strbufobject import joined2
+        return joined2(str1, str2)
     else:
         return wrapstr(space, str1 + str2)
 

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_dictmultiobject.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_dictmultiobject.py	Tue Oct 12 14:42:59 2010
@@ -602,6 +602,15 @@
                 classofinstance=classofinstance,
                 from_strdict_shared=from_strdict_shared)
 
+    def finditem_str(self, w_dict, s):
+        return w_dict.getitem_str(s) # assume it's a multidict
+
+    def setitem_str(self, w_dict, s, w_value):
+        return w_dict.setitem_str(s, w_value) # assume it's a multidict
+
+    def delitem(self, w_dict, w_s):
+        return w_dict.delitem(w_s) # assume it's a multidict
+
     def allocate_instance(self, cls, type):
         return object.__new__(cls)
 
@@ -611,7 +620,7 @@
     w_StopIteration = StopIteration
     w_None = None
     StringObjectCls = FakeString
-    w_dict = None
+    w_dict = W_DictMultiObject
     iter = iter
     fixedview = list
     listview  = list
@@ -687,6 +696,14 @@
         assert self.impl.length() == 0
         self.check_not_devolved()
 
+    def test_clear(self):
+        self.fill_impl()
+        assert self.impl.length() == 2
+        self.impl.clear()
+        assert self.impl.length() == 0
+        self.check_not_devolved()
+
+
     def test_keys(self):
         self.fill_impl()
         keys = self.impl.keys()

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_shadowtracking.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_shadowtracking.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/test/test_shadowtracking.py	Tue Oct 12 14:42:59 2010
@@ -3,7 +3,8 @@
 
 class TestShadowTracking(object):
     def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withshadowtracking": True})
+        cls.space = gettestobjspace(**{"objspace.std.withshadowtracking": True,
+                                       "objspace.std.withmapdict": False})
 
     def test_simple_shadowing(self):
         space = self.space

Modified: pypy/branch/32ptr-on-64bit/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/objspace/std/typeobject.py	Tue Oct 12 14:42:59 2010
@@ -75,7 +75,9 @@
                           'weakrefable',
                           'hasdict',
                           'nslots',
-                          'instancetypedef']
+                          'instancetypedef',
+                          'terminator',
+                          ]
 
     # for config.objspace.std.getattributeshortcut
     # (False is a conservative default, fixed during real usage)
@@ -116,6 +118,12 @@
                 # dict_w of any of the types in the mro changes, or if the mro
                 # itself changes
                 w_self._version_tag = VersionTag()
+        if space.config.objspace.std.withmapdict:
+            from pypy.objspace.std.mapdict import DictTerminator, NoDictTerminator
+            if w_self.hasdict:
+                w_self.terminator = DictTerminator(space, w_self)
+            else:
+                w_self.terminator = NoDictTerminator(space, w_self)
 
     def mutated(w_self):
         space = w_self.space

Modified: pypy/branch/32ptr-on-64bit/pypy/rlib/_rsocket_rffi.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rlib/_rsocket_rffi.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rlib/_rsocket_rffi.py	Tue Oct 12 14:42:59 2010
@@ -324,10 +324,11 @@
                                ('sll_hatype', rffi.INT),
                                ('sll_addr', rffi.CFixedArray(rffi.CHAR, 8)),
                                ('sll_halen', rffi.INT)],
-                              )
+                              ifdef='AF_PACKET')
 
     CConfig.ifreq = platform.Struct('struct ifreq', [('ifr_ifindex', rffi.INT),
-                                 ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))])
+                                 ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))],
+                                    ifdef='AF_PACKET')
 
 if _WIN32:
     CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP)
@@ -532,8 +533,9 @@
     socketpair_t = rffi.CArray(socketfd_type)
     socketpair = external('socketpair', [rffi.INT, rffi.INT, rffi.INT,
                           lltype.Ptr(socketpair_t)], rffi.INT)
-    ioctl = external('ioctl', [socketfd_type, rffi.INT, lltype.Ptr(ifreq)],
-                     rffi.INT)
+    if ifreq is not None:
+        ioctl = external('ioctl', [socketfd_type, rffi.INT, lltype.Ptr(ifreq)],
+                         rffi.INT)
 
 if _WIN32:
     ioctlsocket = external('ioctlsocket',

Modified: pypy/branch/32ptr-on-64bit/pypy/rlib/rmmap.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rlib/rmmap.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rlib/rmmap.py	Tue Oct 12 14:42:59 2010
@@ -50,8 +50,8 @@
     constant_names = ['MAP_SHARED', 'MAP_PRIVATE',
                       'PROT_READ', 'PROT_WRITE',
                       'MS_SYNC']
-    opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS', 'MAP_FIXED',
-                          'PROT_EXEC',
+    opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS', 'MAP_NORESERVE',
+                          'MAP_FIXED', 'PROT_EXEC',
                           'MAP_DENYWRITE', 'MAP_EXECUTABLE']
     for name in constant_names:
         setattr(CConfig, name, rffi_platform.ConstantInteger(name))

Modified: pypy/branch/32ptr-on-64bit/pypy/rlib/rstring.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rlib/rstring.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rlib/rstring.py	Tue Oct 12 14:42:59 2010
@@ -54,6 +54,7 @@
         self.l = []
 
     def append(self, s):
+        assert isinstance(s, self._type)
         self.l.append(s)
 
     def append_slice(self, s, start, end):
@@ -63,11 +64,16 @@
     def append_multiple_char(self, c, times):
         self.l.append(c * times)
 
+    def getlength(self):
+        return len(self.build())
+
 class StringBuilder(AbstractStringBuilder):
+    _type = str
     def build(self):
         return "".join(self.l)
 
 class UnicodeBuilder(AbstractStringBuilder):
+    _type = unicode
     def build(self):
         return u''.join(self.l)
 
@@ -121,9 +127,12 @@
         assert s_times.nonneg
         return s_None
 
+    def method_getlength(self):
+        return SomeInteger(nonneg=True)
+
     def method_build(self):
         return SomeString()
-    
+
     def rtyper_makerepr(self, rtyper):
         return rtyper.type_system.rbuilder.stringbuilder_repr
 
@@ -146,6 +155,9 @@
         assert s_times.nonneg
         return s_None
 
+    def method_getlength(self):
+        return SomeInteger(nonneg=True)
+
     def method_build(self):
         return SomeUnicodeString()
     

Modified: pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rsocket.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rsocket.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rsocket.py	Tue Oct 12 14:42:59 2010
@@ -437,3 +437,31 @@
             foo = self.serv.accept()
         py.test.raises(SocketError, raise_error)
 
+def _test_cond_include(cond):
+    # Test that _rsocket_rffi is importable even on platforms where
+    # AF_PACKET or AF_NETLINK is not defined.
+    import re
+    from pypy.rlib import _rsocket_rffi
+    srcfile = _rsocket_rffi.__file__
+    if srcfile.lower().endswith('c') or srcfile.lower().endswith('o'):
+        srcfile = srcfile[:-1]      # .pyc => .py
+    assert srcfile.lower().endswith('.py')
+    sourcelines = open(srcfile, 'rb').read().splitlines()
+    found = False
+    for i, line in enumerate(sourcelines):
+        line2 = re.sub(r"(\s*COND_HEADER\s*=)",
+                      r"\1'#undef %s\\n'+" % cond,
+                      line)
+        if line2 != line:
+            found = True
+            sourcelines[i] = line2
+    assert found
+    d = {}
+    sourcelines.append('')
+    exec '\n'.join(sourcelines) in d
+
+def test_no_AF_PACKET():
+    _test_cond_include('AF_PACKET')
+
+def test_no_AF_NETLINK():
+    _test_cond_include('AF_NETLINK')

Modified: pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rstring.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rstring.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rlib/test/test_rstring.py	Tue Oct 12 14:42:59 2010
@@ -29,6 +29,7 @@
     s = StringBuilder()
     s.append("a")
     s.append("abc")
+    assert s.getlength() == len('aabc')
     s.append("a")
     s.append_slice("abc", 1, 2)
     s.append_multiple_char('d', 4)
@@ -39,6 +40,7 @@
     s.append(u'a')
     s.append(u'abc')
     s.append_slice(u'abcdef', 1, 2)
+    assert s.getlength() == len('aabcb')
     s.append_multiple_char('d', 4)
     assert s.build() == 'aabcbdddd'
     assert isinstance(s.build(), unicode)

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/ll2ctypes.py	Tue Oct 12 14:42:59 2010
@@ -69,7 +69,7 @@
                 PIECESIZE = 0x08000000
         PIECES = 10
         m = rmmap.mmap(-1, PIECES * PIECESIZE,
-                       rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS,
+                       rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS|rmmap.MAP_NORESERVE,
                        rmmap.PROT_READ|rmmap.PROT_WRITE)
         m.close = lambda : None    # leak instead of giving a spurious
                                    # error at CPython's shutdown

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rbuilder.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rbuilder.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rbuilder.py	Tue Oct 12 14:42:59 2010
@@ -100,6 +100,10 @@
         ll_builder.used = used
 
     @staticmethod
+    def ll_getlength(ll_builder):
+        return ll_builder.used
+
+    @staticmethod
     def ll_build(ll_builder):
         final_size = ll_builder.used
         assert final_size >= 0

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py	Tue Oct 12 14:42:59 2010
@@ -331,10 +331,9 @@
             fields['__class__'] = 'typeptr', r, r
         else:
             # instance attributes
-            if llfields is None:
-                llfields = []
             attrs = self.classdef.attrs.items()
             attrs.sort()
+            myllfields = []
             for name, attrdef in attrs:
                 if not attrdef.readonly:
                     r = self.rtyper.getrepr(attrdef.s_value)
@@ -344,7 +343,25 @@
                     else:
                         internal_r = r
                     fields[name] = mangled_name, r, internal_r
-                    llfields.append((mangled_name, internal_r.lowleveltype))
+                    myllfields.append((mangled_name, internal_r.lowleveltype))
+
+            # Sort the instance attributes by decreasing "likely size",
+            # as reported by rffi.sizeof(), to minimize padding holes in C.
+            # Fields of the same size are sorted by name (by attrs.sort()
+            # above) just to minimize randomness.
+            def keysize((_, T)):
+                if T is lltype.Void:
+                    return None
+                from pypy.rpython.lltypesystem.rffi import sizeof
+                try:
+                    return -sizeof(T)
+                except StandardError:
+                    return None
+            myllfields.sort(key = keysize)
+            if llfields is None:
+                llfields = myllfields
+            else:
+                llfields = llfields + myllfields
 
             self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef,
                                          self.gcflavor)

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/module/ll_time.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/module/ll_time.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/module/ll_time.py	Tue Oct 12 14:42:59 2010
@@ -108,7 +108,7 @@
 
                 errcode = -1
                 if self.GETTIMEOFDAY_NO_TZ:
-                    errcode = g_gettimeofday(t)
+                    errcode = c_gettimeofday(t)
                 else:
                     errcode = c_gettimeofday(t, void)
 

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/rbuilder.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/rbuilder.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/rbuilder.py	Tue Oct 12 14:42:59 2010
@@ -36,8 +36,12 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_append_multiple_char, *vlist)
 
+    def rtype_method_getlength(self, hop):
+        vlist = hop.inputargs(self)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll_getlength, *vlist)
+
     def rtype_method_build(self, hop):
         vlist = hop.inputargs(self)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_build, *vlist)
-

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/rtyper.py	Tue Oct 12 14:42:59 2010
@@ -421,7 +421,7 @@
             assert noexclink.exitcase is None
             if pos == "removed":
                 # the exception cannot actually occur at all.
-                # See for example rspecialcase.rtype_call_specialcase().
+                # This is set by calling exception_cannot_occur().
                 # We just remove all exception links.
                 block.exitswitch = None
                 block.exits = block.exits[:1]
@@ -1019,7 +1019,7 @@
 from pypy.rpython import rint, rbool, rfloat
 from pypy.rpython import rrange
 from pypy.rpython import rstr, rdict, rlist
-from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase
+from pypy.rpython import rclass, rbuiltin, rpbc
 from pypy.rpython import rexternalobj
 from pypy.rpython import rptr
 from pypy.rpython import rgeneric

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rbuilder.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rbuilder.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rbuilder.py	Tue Oct 12 14:42:59 2010
@@ -1,4 +1,4 @@
-
+import py
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.rpython.lltypesystem.rbuilder import *
 from pypy.rpython.annlowlevel import llstr, hlstr
@@ -55,8 +55,29 @@
         assert res == 'aabcabcdefbuuuu'
         assert isinstance(res, unicode)
 
+    def test_string_getlength(self):
+        def func():
+            s = StringBuilder()
+            s.append("a")
+            s.append("abc")
+            return s.getlength()
+        res = self.interpret(func, [])
+        assert res == 4
+
+    def test_unicode_getlength(self):
+        def func():
+            s = UnicodeBuilder()
+            s.append(u"a")
+            s.append(u"abc")
+            return s.getlength()
+        res = self.interpret(func, [])
+        assert res == 4
+
 class TestLLtype(BaseTestStringBuilder, LLRtypeMixin):
     pass
 
 class TestOOtype(BaseTestStringBuilder, OORtypeMixin):
-    pass
+    def test_string_getlength(self):
+        py.test.skip("getlength(): not implemented on ootype")
+    def test_unicode_getlength(self):
+        py.test.skip("getlength(): not implemented on ootype")

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rclass.py	Tue Oct 12 14:42:59 2010
@@ -3,7 +3,7 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.ootypesystem import ootype
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_longlong
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.objspace.flow.model import summary
 
@@ -1001,6 +1001,40 @@
         res = self.interpret(f, [5])
         assert res == 0
 
+    def test_order_of_fields(self):
+        class A(object):
+            pass
+        def f(n):
+            a = A()
+            a.as_int = n
+            a.as_char = chr(n)
+            a.as_unichar = unichr(n)
+            a.as_double = n + 0.5
+            a.as_bool = bool(n)
+            a.as_void = None
+            a.as_longlong = r_longlong(n)
+            a.as_reference = A()
+            return a
+
+        res = self.interpret(f, [5])
+        names = list(typeOf(res).TO._names)
+        i = names.index('inst_as_int')
+        c = names.index('inst_as_char')
+        u = names.index('inst_as_unichar')
+        d = names.index('inst_as_double')
+        b = names.index('inst_as_bool')
+        v = names.index('inst_as_void')
+        l = names.index('inst_as_longlong')
+        r = names.index('inst_as_reference')
+        assert v == 1      # void fields are first
+        assert sorted([c, b]) == [7, 8]
+        if sys.maxint == 2147483647:
+            assert sorted([u, i, r]) == [4, 5, 6]        # 32-bit types
+            assert sorted([d, l]) == [2, 3]              # 64-bit types
+        else:
+            assert sorted([u]) == [6]                    # 32-bit types
+            assert sorted([i, r, d, l]) == [2, 3, 4, 5]  # 64-bit types
+
 
 class TestOOtype(BaseTestRclass, OORtypeMixin):
 

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track5.s
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track5.s	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/test/elf/track5.s	Tue Oct 12 14:42:59 2010
@@ -44,7 +44,7 @@
 	addl	%eax, %ebx
 	jmp	.L1221
 .L1227:
-	call	RPyAbort
+	;;call	RPyAbort
 	cmpl	12(%esi), %ebx
 	jb	.L1229
 	addl	$20, %esp

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/gcc/trackgcroot.py	Tue Oct 12 14:42:59 2010
@@ -46,6 +46,7 @@
         self.findlabels()
         self.parse_instructions()
         try:
+            self.trim_unreachable_instructions()
             self.find_noncollecting_calls()
             if not self.list_collecting_call_insns():
                 return []
@@ -122,6 +123,26 @@
                 assert label not in self.labels, "duplicate label: %s" % label
                 self.labels[label] = Label(label, lineno)
 
+    def trim_unreachable_instructions(self):
+        reached = set([self.insns[0]])
+        prevlen = 0
+        while len(reached) > prevlen:
+            prevlen = len(reached)
+            for insn in self.insns:
+                if insn not in reached:
+                    for previnsn in insn.previous_insns:
+                        if previnsn in reached:
+                            # this instruction is reachable too
+                            reached.add(insn)
+                            break
+        # now kill all unreachable instructions
+        i = 0
+        while i < len(self.insns):
+            if self.insns[i] in reached:
+                i += 1
+            else:
+                del self.insns[i]
+
     def find_noncollecting_calls(self):
         cannot_collect = {}
         for line in self.lines:
@@ -752,7 +773,7 @@
                     target, = sources
 
         if target in self.FUNCTIONS_NOT_RETURNING:
-            return [InsnStop(target), InsnCannotFollowEsp()]
+            return [InsnStop(target)]
         if self.format == 'mingw32' and target == '__alloca':
             # in functions with large stack requirements, windows
             # needs a call to _alloca(), to turn reserved pages

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/src/signals.h
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/src/signals.h	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/src/signals.h	Tue Oct 12 14:42:59 2010
@@ -6,20 +6,6 @@
 
 #include <limits.h>
 
-#ifndef LONG_MAX
-#if SIZEOF_LONG == 4
-#define LONG_MAX 0X7FFFFFFFL
-#elif SIZEOF_LONG == 8
-#define LONG_MAX 0X7FFFFFFFFFFFFFFFL
-#else
-#error "could not set LONG_MAX in pyport.h"
-#endif
-#endif
-
-#ifndef LONG_MIN
-#define LONG_MIN (-LONG_MAX-1)
-#endif
-
 #include <stdlib.h>
 
 #ifdef MS_WINDOWS
@@ -28,10 +14,6 @@
 
 #include <signal.h>
 
-#ifndef SIG_ERR
-#define SIG_ERR ((PyOS_sighandler_t)(-1))
-#endif
-
 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
 #define NSIG 12
 #include <process.h>
@@ -65,11 +47,11 @@
 /* utility to poll for signals that arrived */
 int pypysig_poll(void);   /* => signum or -1 */
 
-/* When a signal is received, the high bit of pypysig_occurred is set.
-   After all signals are processed by pypysig_poll(), the high bit is
+/* When a signal is received, the bit 30 of pypysig_occurred is set.
+   After all signals are processed by pypysig_poll(), the bit 30 is
    cleared again.  The variable is exposed and RPython code is free to
    use the other bits in any way. */
-#define PENDING_SIGNAL_BIT   (LONG_MIN)   /* high bit */
+#define PENDING_SIGNAL_BIT   (1 << 30)
 /* This is a struct for the JIT. See interp_signal.py. */
 struct pypysig_long_struct {
     long value;

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/goal/ann_override.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/goal/ann_override.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/goal/ann_override.py	Tue Oct 12 14:42:59 2010
@@ -27,21 +27,6 @@
         pol.pypytypes = {}
         pol.single_space = single_space
 
-    #def override__wrap_exception_cls(pol, space, x):
-    #    import pypy.objspace.std.typeobject as typeobject
-    #    clsdef = getbookkeeper().getuniqueclassdef(typeobject.W_TypeObject)
-    #    return annmodel.SomeInstance(clsdef, can_be_None=True)
-    #
-    #def override__fake_object(pol, space, x):
-    #    from pypy.interpreter import typedef
-    #    clsdef = getbookkeeper().getuniqueclassdef(typedef.W_Root)
-    #    return annmodel.SomeInstance(clsdef)    
-    #
-    #def override__cpy_compile(pol, self, source, filename, mode, flags):
-    #    from pypy.interpreter import pycode
-    #    clsdef = getbookkeeper().getuniqueclassdef(pycode.PyCode)
-    #    return annmodel.SomeInstance(clsdef)    
-
     def specialize__wrap(pol,  funcdesc, args_s):
         from pypy.interpreter.baseobjspace import Wrappable
         from pypy.annotation.classdef import ClassDef

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/jvm/test/test_class.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/jvm/test/test_class.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/jvm/test/test_class.py	Tue Oct 12 14:42:59 2010
@@ -1,6 +1,6 @@
 import py
 from pypy.translator.jvm.test.runtest import JvmTest
-from pypy.translator.oosupport.test_template.class_ import BaseTestClass, BaseTestSpecialcase
+from pypy.translator.oosupport.test_template.class_ import BaseTestClass
 
 class TestJvmClass(JvmTest, BaseTestClass):    
     def test_overridden_classattr_as_defaults(self):
@@ -26,6 +26,3 @@
             
     def test_specialize_methods(self):
         py.test.skip('ABSTRACT METHOD FIX: RE-TEST AFTER MERGE')
-
-class TestJvmSpecialCase(JvmTest, BaseTestSpecialcase):
-    pass

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/oosupport/test_template/class_.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/oosupport/test_template/class_.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/oosupport/test_template/class_.py	Tue Oct 12 14:42:59 2010
@@ -1,6 +1,5 @@
 import py
 from pypy.rpython.test import test_rclass
-from pypy.rpython.test.test_rspecialcase import BaseTestRspecialcase
 
 class BaseTestClass(test_rclass.TestOOtype):
     def test_abstract_method(self):
@@ -66,6 +65,3 @@
 
     def test_cast_object_mix_null(self):
         py.test.skip('cannot return ootype.NULL from translated functions')
-
-class BaseTestSpecialcase(BaseTestRspecialcase):
-    pass



More information about the Pypy-commit mailing list