[pypy-commit] pypy py3k: merge default

pjenvey noreply at buildbot.pypy.org
Sun Nov 30 23:12:42 CET 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r74767:e01964ac6c50
Date: 2014-11-30 11:51 -0800
http://bitbucket.org/pypy/pypy/changeset/e01964ac6c50/

Log:	merge default

diff too long, truncating to 2000 out of 3374 lines

diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -655,6 +655,21 @@
         """Create new Popen instance."""
         _cleanup()
 
+        # --- PyPy hack, see _pypy_install_libs_after_virtualenv() ---
+        # match arguments passed by different versions of virtualenv
+        if args[1:] in (
+            ['-c', 'import sys; print(sys.prefix)'],        # 1.6 10ba3f3c
+            ['-c', "\nimport sys\nprefix = sys.prefix\n"    # 1.7 0e9342ce
+             "if sys.version_info[0] == 3:\n"
+             "    prefix = prefix.encode('utf8')\n"
+             "if hasattr(sys.stdout, 'detach'):\n"
+             "    sys.stdout = sys.stdout.detach()\n"
+             "elif hasattr(sys.stdout, 'buffer'):\n"
+             "    sys.stdout = sys.stdout.buffer\nsys.stdout.write(prefix)\n"],
+            ['-c', 'import sys;out=sys.stdout;getattr(out, "buffer"'
+             ', out).write(sys.prefix.encode("utf-8"))']):  # 1.7.2 a9454bce
+            _pypy_install_libs_after_virtualenv(args[0])
+
         if not isinstance(bufsize, (int, long)):
             raise TypeError("bufsize must be an integer")
 
@@ -1560,6 +1575,27 @@
             self.send_signal(signal.SIGKILL)
 
 
+def _pypy_install_libs_after_virtualenv(target_executable):
+    # https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
+    #
+    # PyPy 2.4.1 turned --shared on by default.  This means the pypy binary
+    # depends on the 'libpypy-c.so' shared library to be able to run.
+    # The virtualenv code existing at the time did not account for this
+    # and would break.  Try to detect that we're running under such a
+    # virtualenv in the "Testing executable with" phase and copy the
+    # library ourselves.
+    caller = sys._getframe(2)
+    if ('virtualenv_version' in caller.f_globals and
+                  'copyfile' in caller.f_globals):
+        dest_dir = sys.pypy_resolvedirof(target_executable)
+        src_dir = sys.pypy_resolvedirof(sys.executable)
+        for libname in ['libpypy-c.so']:
+            dest_library = os.path.join(dest_dir, libname)
+            src_library = os.path.join(src_dir, libname)
+            if os.path.exists(src_library):
+                caller.f_globals['copyfile'](src_library, dest_library)
+
+
 def _demo_posix():
     #
     # Example 1: Simple redirection: Get process list
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -205,23 +205,28 @@
 The above is true both in CPython and in PyPy.  Differences
 can occur about whether a built-in function or method will
 call an overridden method of *another* object than ``self``.
-In PyPy, they are generally always called, whereas not in
-CPython.  For example, in PyPy, ``dict1.update(dict2)``
-considers that ``dict2`` is just a general mapping object, and
-will thus call overridden ``keys()``  and ``__getitem__()``
-methods on it.  So the following code prints ``42`` on PyPy
-but ``foo`` on CPython::
+In PyPy, they are often called in cases where CPython would not.
+Two examples::
 
-    >>>> class D(dict):
-    ....     def __getitem__(self, key):
-    ....         return 42
-    ....
-    >>>>
-    >>>> d1 = {}
-    >>>> d2 = D(a='foo')
-    >>>> d1.update(d2)
-    >>>> print d1['a']
-    42
+    class D(dict):
+        def __getitem__(self, key):
+            return "%r from D" % (key,)
+
+    class A(object):
+        pass
+
+    a = A()
+    a.__dict__ = D()
+    a.foo = "a's own foo"
+    print a.foo
+    # CPython => a's own foo
+    # PyPy => 'foo' from D
+
+    glob = D(foo="base item")
+    loc = {}
+    exec "print foo" in glob, loc
+    # CPython => base item
+    # PyPy => 'foo' from D
 
 
 Mutating classes of objects which are already used as dictionary keys
@@ -292,6 +297,9 @@
 above types will return a value that is computed from the argument, and can
 thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
 
+Notably missing from the list above are ``str`` and ``unicode``.  If your
+code relies on comparing strings with ``is``, then it might break in PyPy.
+
 
 Miscellaneous
 -------------
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -1,15 +1,13 @@
-"""
-Python control flow graph generation and bytecode assembly.
-"""
+"""Python control flow graph generation and bytecode assembly."""
 
-from pypy.interpreter.astcompiler import ast, consts, symtable
-from pypy.interpreter import pycode
+from rpython.rlib import rfloat
+from rpython.rlib.objectmodel import specialize, we_are_translated
+
+from pypy.interpreter.astcompiler import ast, consts, misc, symtable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.pycode import PyCode
 from pypy.tool import stdlib_opcode as ops
 
-from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib import rfloat
-
 
 class Instruction(object):
     """Represents a single opcode."""
@@ -21,14 +19,12 @@
         self.has_jump = False
 
     def size(self):
-        """Return the size of bytes of this instruction when it is encoded."""
+        """Return the size of bytes of this instruction when it is
+        encoded.
+        """
         if self.opcode >= ops.HAVE_ARGUMENT:
-            if self.arg > 0xFFFF:
-                return 6
-            else:
-                return 3
-        else:
-            return 1
+            return (6 if self.arg > 0xFFFF else 3)
+        return 1
 
     def jump_to(self, target, absolute=False):
         """Indicate the target this jump instruction.
@@ -54,9 +50,9 @@
 class Block(object):
     """A basic control flow block.
 
-    It has one entry point and several possible exit points.  Its instructions
-    may be jumps to other blocks, or if control flow reaches the end of the
-    block, it continues to next_block.
+    It has one entry point and several possible exit points.  Its
+    instructions may be jumps to other blocks, or if control flow
+    reaches the end of the block, it continues to next_block.
     """
 
     def __init__(self):
@@ -71,10 +67,10 @@
             stack.append(nextblock)
 
     def post_order(self):
-        """Return this block and its children in post order.
-        This means that the graph of blocks is first cleaned up to
-        ignore back-edges, thus turning it into a DAG.  Then the DAG
-        is linearized.  For example:
+        """Return this block and its children in post order.  This means
+        that the graph of blocks is first cleaned up to ignore
+        back-edges, thus turning it into a DAG.  Then the DAG is
+        linearized.  For example:
 
                    A --> B -\           =>     [A, D, B, C]
                      \-> D ---> C
@@ -105,7 +101,9 @@
         return resultblocks
 
     def code_size(self):
-        """Return the encoded size of all the instructions in this block."""
+        """Return the encoded size of all the instructions in this
+        block.
+        """
         i = 0
         for instr in self.instructions:
             i += instr.size()
@@ -141,6 +139,7 @@
             i += 1
     return result
 
+
 @specialize.argtype(0)
 def _iter_to_dict(iterable, offset=0):
     result = {}
@@ -302,11 +301,11 @@
     def _resolve_block_targets(self, blocks):
         """Compute the arguments of jump instructions."""
         last_extended_arg_count = 0
-        # The reason for this loop is extended jumps.  EXTENDED_ARG extends the
-        # bytecode size, so it might invalidate the offsets we've already given.
-        # Thus we have to loop until the number of extended args is stable.  Any
-        # extended jump at all is extremely rare, so performance is not too
-        # concerning.
+        # The reason for this loop is extended jumps.  EXTENDED_ARG
+        # extends the bytecode size, so it might invalidate the offsets
+        # we've already given.  Thus we have to loop until the number of
+        # extended args is stable.  Any extended jump at all is
+        # extremely rare, so performance is not too concerning.
         while True:
             extended_arg_count = 0
             offset = 0
@@ -332,7 +331,8 @@
                                     instr.opcode = ops.JUMP_ABSOLUTE
                                     absolute = True
                                 elif target_op == ops.RETURN_VALUE:
-                                    # Replace JUMP_* to a RETURN into just a RETURN
+                                    # Replace JUMP_* to a RETURN into
+                                    # just a RETURN
                                     instr.opcode = ops.RETURN_VALUE
                                     instr.arg = 0
                                     instr.has_jump = False
@@ -347,7 +347,8 @@
                         instr.arg = jump_arg
                         if jump_arg > 0xFFFF:
                             extended_arg_count += 1
-            if extended_arg_count == last_extended_arg_count and not force_redo:
+            if (extended_arg_count == last_extended_arg_count and
+                not force_redo):
                 break
             else:
                 last_extended_arg_count = extended_arg_count
@@ -362,12 +363,14 @@
         while True:
             try:
                 w_key = space.next(w_iter)
-            except OperationError, e:
+            except OperationError as e:
                 if not e.match(space, space.w_StopIteration):
                     raise
                 break
             w_index = space.getitem(w_consts, w_key)
-            consts_w[space.int_w(w_index)] = space.getitem(w_key, first)
+            w_constant = space.getitem(w_key, first)
+            w_constant = misc.intern_if_common_string(space, w_constant)
+            consts_w[space.int_w(w_index)] = w_constant
         return consts_w
 
     def _get_code_flags(self):
@@ -435,15 +438,16 @@
                         continue
                     addr = offset - current_off
                     # Python assumes that lineno always increases with
-                    # increasing bytecode address (lnotab is unsigned char).
-                    # Depending on when SET_LINENO instructions are emitted this
-                    # is not always true.  Consider the code:
+                    # increasing bytecode address (lnotab is unsigned
+                    # char).  Depending on when SET_LINENO instructions
+                    # are emitted this is not always true.  Consider the
+                    # code:
                     #     a = (1,
                     #          b)
-                    # In the bytecode stream, the assignment to "a" occurs after
-                    # the loading of "b".  This works with the C Python compiler
-                    # because it only generates a SET_LINENO instruction for the
-                    # assignment.
+                    # In the bytecode stream, the assignment to "a"
+                    # occurs after the loading of "b".  This works with
+                    # the C Python compiler because it only generates a
+                    # SET_LINENO instruction for the assignment.
                     if line or addr:
                         while addr > 255:
                             push(chr(255))
@@ -488,23 +492,23 @@
         # (Only) inherit compilerflags in PyCF_MASK
         flags |= (self.compile_info.flags & consts.PyCF_MASK)
         bytecode = ''.join([block.get_code() for block in blocks])
-        return pycode.PyCode(self.space,
-                             self.argcount,
-                             self.kwonlyargcount,
-                             len(self.var_names),
-                             stack_depth,
-                             flags,
-                             bytecode,
-                             list(consts_w),
-                             names,
-                             var_names,
-                             self.compile_info.filename,
-                             self.name,
-                             self.first_lineno,
-                             lnotab,
-                             free_names,
-                             cell_names,
-                             self.compile_info.hidden_applevel)
+        return PyCode(self.space,
+                      self.argcount,
+                      self.kwonlyargcount,
+                      len(self.var_names),
+                      stack_depth,
+                      flags,
+                      bytecode,
+                      list(consts_w),
+                      names,
+                      var_names,
+                      self.compile_info.filename,
+                      self.name,
+                      self.first_lineno,
+                      lnotab,
+                      free_names,
+                      cell_names,
+                      self.compile_info.hidden_applevel)
 
 
 def _list_from_dict(d, offset=0):
@@ -515,116 +519,116 @@
 
 
 _static_opcode_stack_effects = {
-    ops.NOP : 0,
-    ops.STOP_CODE : 0,
+    ops.NOP: 0,
+    ops.STOP_CODE: 0,
 
-    ops.POP_TOP : -1,
-    ops.ROT_TWO : 0,
-    ops.ROT_THREE : 0,
-    ops.DUP_TOP : 1,
-    ops.DUP_TOP_TWO : 2,
+    ops.POP_TOP: -1,
+    ops.ROT_TWO: 0,
+    ops.ROT_THREE: 0,
+    ops.DUP_TOP: 1,
+    ops.DUP_TOP_TWO: 2,
 
-    ops.UNARY_POSITIVE : 0,
-    ops.UNARY_NEGATIVE : 0,
-    ops.UNARY_NOT : 0,
-    ops.UNARY_INVERT : 0,
+    ops.UNARY_POSITIVE: 0,
+    ops.UNARY_NEGATIVE: 0,
+    ops.UNARY_NOT: 0,
+    ops.UNARY_INVERT: 0,
 
-    ops.LIST_APPEND : -1,
-    ops.SET_ADD : -1,
-    ops.MAP_ADD : -2,
-    ops.STORE_MAP : -2,
+    ops.LIST_APPEND: -1,
+    ops.SET_ADD: -1,
+    ops.MAP_ADD: -2,
+    ops.STORE_MAP: -2,
 
-    ops.BINARY_POWER : -1,
-    ops.BINARY_MULTIPLY : -1,
-    ops.BINARY_MODULO : -1,
-    ops.BINARY_ADD : -1,
-    ops.BINARY_SUBTRACT : -1,
-    ops.BINARY_SUBSCR : -1,
-    ops.BINARY_FLOOR_DIVIDE : -1,
-    ops.BINARY_TRUE_DIVIDE : -1,
-    ops.BINARY_LSHIFT : -1,
-    ops.BINARY_RSHIFT : -1,
-    ops.BINARY_AND : -1,
-    ops.BINARY_OR : -1,
-    ops.BINARY_XOR : -1,
+    ops.BINARY_POWER: -1,
+    ops.BINARY_MULTIPLY: -1,
+    ops.BINARY_MODULO: -1,
+    ops.BINARY_ADD: -1,
+    ops.BINARY_SUBTRACT: -1,
+    ops.BINARY_SUBSCR: -1,
+    ops.BINARY_FLOOR_DIVIDE: -1,
+    ops.BINARY_TRUE_DIVIDE: -1,
+    ops.BINARY_LSHIFT: -1,
+    ops.BINARY_RSHIFT: -1,
+    ops.BINARY_AND: -1,
+    ops.BINARY_OR: -1,
+    ops.BINARY_XOR: -1,
 
-    ops.INPLACE_FLOOR_DIVIDE : -1,
-    ops.INPLACE_TRUE_DIVIDE : -1,
-    ops.INPLACE_ADD : -1,
-    ops.INPLACE_SUBTRACT : -1,
-    ops.INPLACE_MULTIPLY : -1,
-    ops.INPLACE_MODULO : -1,
-    ops.INPLACE_POWER : -1,
-    ops.INPLACE_LSHIFT : -1,
-    ops.INPLACE_RSHIFT : -1,
-    ops.INPLACE_AND : -1,
-    ops.INPLACE_OR : -1,
-    ops.INPLACE_XOR : -1,
+    ops.INPLACE_FLOOR_DIVIDE: -1,
+    ops.INPLACE_TRUE_DIVIDE: -1,
+    ops.INPLACE_ADD: -1,
+    ops.INPLACE_SUBTRACT: -1,
+    ops.INPLACE_MULTIPLY: -1,
+    ops.INPLACE_MODULO: -1,
+    ops.INPLACE_POWER: -1,
+    ops.INPLACE_LSHIFT: -1,
+    ops.INPLACE_RSHIFT: -1,
+    ops.INPLACE_AND: -1,
+    ops.INPLACE_OR: -1,
+    ops.INPLACE_XOR: -1,
 
-    ops.STORE_SUBSCR : -2,
-    ops.DELETE_SUBSCR : -2,
+    ops.STORE_SUBSCR: -2,
+    ops.DELETE_SUBSCR: -2,
 
-    ops.GET_ITER : 0,
-    ops.FOR_ITER : 1,
-    ops.BREAK_LOOP : 0,
-    ops.CONTINUE_LOOP : 0,
-    ops.SETUP_LOOP : 0,
+    ops.GET_ITER: 0,
+    ops.FOR_ITER: 1,
+    ops.BREAK_LOOP: 0,
+    ops.CONTINUE_LOOP: 0,
+    ops.SETUP_LOOP: 0,
 
-    ops.PRINT_EXPR : -1,
+    ops.PRINT_EXPR: -1,
 
-    ops.WITH_CLEANUP : -1,
-    ops.LOAD_BUILD_CLASS : 1,
-    ops.STORE_LOCALS : -1,
-    ops.POP_BLOCK : 0,
-    ops.POP_EXCEPT : 0,
-    ops.END_FINALLY : -1,
-    ops.SETUP_WITH : 1,
-    ops.SETUP_FINALLY : 0,
-    ops.SETUP_EXCEPT : 4,
+    ops.WITH_CLEANUP: -1,
+    ops.LOAD_BUILD_CLASS: 1,
+    ops.STORE_LOCALS: -1,
+    ops.POP_BLOCK: 0,
+    ops.POP_EXCEPT: 0,
+    ops.END_FINALLY: -1,
+    ops.SETUP_WITH: 1,
+    ops.SETUP_FINALLY: 0,
+    ops.SETUP_EXCEPT: 4,
 
-    ops.RETURN_VALUE : -1,
-    ops.YIELD_VALUE : 0,
-    ops.BUILD_MAP : 1,
-    ops.BUILD_SET : 1,
-    ops.COMPARE_OP : -1,
+    ops.RETURN_VALUE: -1,
+    ops.YIELD_VALUE: 0,
+    ops.BUILD_MAP: 1,
+    ops.BUILD_SET: 1,
+    ops.COMPARE_OP: -1,
 
-    ops.LOOKUP_METHOD : 1,
+    ops.LOOKUP_METHOD: 1,
 
-    ops.LOAD_NAME : 1,
-    ops.STORE_NAME : -1,
-    ops.DELETE_NAME : 0,
+    ops.LOAD_NAME: 1,
+    ops.STORE_NAME: -1,
+    ops.DELETE_NAME: 0,
 
-    ops.LOAD_FAST : 1,
-    ops.STORE_FAST : -1,
-    ops.DELETE_FAST : 0,
+    ops.LOAD_FAST: 1,
+    ops.STORE_FAST: -1,
+    ops.DELETE_FAST: 0,
 
-    ops.LOAD_ATTR : 0,
-    ops.STORE_ATTR : -2,
-    ops.DELETE_ATTR : -1,
+    ops.LOAD_ATTR: 0,
+    ops.STORE_ATTR: -2,
+    ops.DELETE_ATTR: -1,
 
-    ops.LOAD_GLOBAL : 1,
-    ops.STORE_GLOBAL : -1,
-    ops.DELETE_GLOBAL : 0,
-    ops.DELETE_DEREF : 0,
-
-    ops.LOAD_CLOSURE : 1,
-    ops.LOAD_DEREF : 1,
-    ops.STORE_DEREF : -1,
+    ops.LOAD_GLOBAL: 1,
+    ops.STORE_GLOBAL: -1,
+    ops.DELETE_GLOBAL: 0,
     ops.DELETE_DEREF: 0,
 
-    ops.LOAD_CONST : 1,
+    ops.LOAD_CLOSURE: 1,
+    ops.LOAD_DEREF: 1,
+    ops.STORE_DEREF: -1,
+    ops.DELETE_DEREF: 0,
 
-    ops.IMPORT_STAR : -1,
-    ops.IMPORT_NAME : -1,
-    ops.IMPORT_FROM : 1,
+    ops.LOAD_CONST: 1,
 
-    ops.JUMP_FORWARD : 0,
-    ops.JUMP_ABSOLUTE : 0,
-    ops.JUMP_IF_TRUE_OR_POP : 0,
-    ops.JUMP_IF_FALSE_OR_POP : 0,
-    ops.POP_JUMP_IF_TRUE : -1,
-    ops.POP_JUMP_IF_FALSE : -1,
-    ops.JUMP_IF_NOT_DEBUG : 0,
+    ops.IMPORT_STAR: -1,
+    ops.IMPORT_NAME: -1,
+    ops.IMPORT_FROM: 1,
+
+    ops.JUMP_FORWARD: 0,
+    ops.JUMP_ABSOLUTE: 0,
+    ops.JUMP_IF_TRUE_OR_POP: 0,
+    ops.JUMP_IF_FALSE_OR_POP: 0,
+    ops.POP_JUMP_IF_TRUE: -1,
+    ops.POP_JUMP_IF_FALSE: -1,
+    ops.JUMP_IF_NOT_DEBUG: 0,
 
     ops.BUILD_LIST_FROM_ARG: 1,
 }
diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -108,6 +108,16 @@
     return "_%s%s" % (klass[i:], name)
 
 
+def intern_if_common_string(space, w_const):
+    # only intern identifier-like strings
+    if not space.is_w(space.type(w_const), space.w_str):
+        return w_const
+    for c in space.str_w(w_const):
+        if not (c.isalnum() or c == '_'):
+            return w_const
+    return space.new_interned_w_str(w_const)
+
+
 def new_identifier(space, name):
     # Check whether there are non-ASCII characters in the identifier; if
     # so, normalize to NFKC
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -279,6 +279,11 @@
                 if w_const is None:
                     return tup
                 consts_w[i] = w_const
+            # intern the string constants packed into the tuple here,
+            # because assemble.py will see the result as just a tuple constant
+            for i in range(len(consts_w)):
+                consts_w[i] = misc.intern_if_common_string(
+                    self.space, consts_w[i])
         else:
             consts_w = []
         w_consts = self.space.newtuple(consts_w)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -15,7 +15,7 @@
     UserDelAction)
 from pypy.interpreter.error import OperationError, new_exception_class, oefmt
 from pypy.interpreter.argument import Arguments
-from pypy.interpreter.miscutils import ThreadLocals
+from pypy.interpreter.miscutils import ThreadLocals, make_weak_value_dictionary
 
 
 __all__ = ['ObjSpace', 'OperationError', 'W_Root']
@@ -362,7 +362,7 @@
         self.builtin_modules = {}
         self.reloading_modules = {}
 
-        self.interned_strings = {}
+        self.interned_strings = make_weak_value_dictionary(self, str, W_Root)
         self.actionflag = ActionFlag()    # changed by the signal module
         self.check_signal_action = None   # changed by the signal module
         self.user_del_action = UserDelAction(self)
@@ -766,25 +766,30 @@
             return self.w_False
 
     def new_interned_w_str(self, w_s):
+        assert isinstance(w_s, W_Root)   # and is not None
         s = self.str_w(w_s)
         if not we_are_translated():
             assert type(s) is str
-        try:
-            return self.interned_strings[s]
-        except KeyError:
-            pass
-        self.interned_strings[s] = w_s
-        return w_s
+        w_s1 = self.interned_strings.get(s)
+        if w_s1 is None:
+            w_s1 = w_s
+            self.interned_strings.set(s, w_s1)
+        return w_s1
 
     def new_interned_str(self, s):
         if not we_are_translated():
             assert type(s) is str
-        try:
-            return self.interned_strings[s]
-        except KeyError:
-            pass
-        w_s = self.interned_strings[s] = self.wrap(s)
-        return w_s
+        w_s1 = self.interned_strings.get(s)
+        if w_s1 is None:
+            w_s1 = self.wrap(s)
+            self.interned_strings.set(s, w_s1)
+        return w_s1
+
+    def is_interned_str(self, s):
+        # interface for marshal_impl
+        if not we_are_translated():
+            assert type(s) is str
+        return self.interned_strings.get(s) is not None
 
     def descr_self_interp_w(self, RequiredClass, w_obj):
         if not isinstance(w_obj, RequiredClass):
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -31,3 +31,19 @@
 
     def getallvalues(self):
         return {0: self._value}
+
+
+def make_weak_value_dictionary(space, keytype, valuetype):
+    "NOT_RPYTHON"
+    if space.config.translation.rweakref:
+        from rpython.rlib.rweakref import RWeakValueDictionary
+        return RWeakValueDictionary(keytype, valuetype)
+    else:
+        class FakeWeakValueDict(object):
+            def __init__(self):
+                self._dict = {}
+            def get(self, key):
+                return self._dict.get(key, None)
+            def set(self, key, value):
+                self._dict[key] = value
+        return FakeWeakValueDict()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -131,7 +131,6 @@
         # class bodies only have CO_NEWLOCALS.
         # CO_NEWLOCALS: make a locals dict unless optimized is also set
         # CO_OPTIMIZED: no locals dict needed at all
-        # NB: this method is overridden in nestedscope.py
         flags = code.co_flags
         if not (flags & pycode.CO_OPTIMIZED):
             if flags & pycode.CO_NEWLOCALS:
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -1094,7 +1094,12 @@
             sys.stdout = out
         output = s.getvalue()
         assert "CALL_METHOD" in output
-            
+
+    def test_interned_strings(self):
+        source = """x = ('foo_bar42', 5); y = 'foo_bar42'; z = x[0]"""
+        exec source
+        assert y is z
+
 
 class AppTestExceptions:
     def test_indentation_error(self):
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -378,3 +378,41 @@
         assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
         space.startup()
         assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
+
+    def test_interned_strings_are_weak(self):
+        import weakref, gc, random
+        space = self.space
+        assert space.config.translation.rweakref
+        w1 = space.new_interned_str("abcdef")
+        w2 = space.new_interned_str("abcdef")
+        assert w2 is w1
+        #
+        # check that 'w1' goes away if we don't hold a reference to it
+        rw1 = weakref.ref(w1)
+        del w1, w2
+        i = 10
+        while rw1() is not None:
+            i -= 1
+            assert i >= 0
+            gc.collect()
+        #
+        s = "foobar%r" % random.random()
+        w0 = space.wrap(s)
+        w1 = space.new_interned_w_str(w0)
+        assert w1 is w0
+        w2 = space.new_interned_w_str(w0)
+        assert w2 is w0
+        w3 = space.wrap(s)
+        assert w3 is not w0
+        w4 = space.new_interned_w_str(w3)
+        assert w4 is w0
+        #
+        # check that 'w0' goes away if we don't hold a reference to it
+        # (even if we hold a reference to 'w3')
+        rw0 = weakref.ref(w0)
+        del w0, w1, w2, w4
+        i = 10
+        while rw0() is not None:
+            i -= 1
+            assert i >= 0
+            gc.collect()
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -147,7 +147,6 @@
     atom_int(tc, int)           puts code and int
     atom_int64(tc, int64)       puts code and int64
     atom_str(tc, str)           puts code, len and string
-    atom_strlist(tc, strlist)   puts code, len and list of strings
 
     building blocks for compound types:
 
@@ -201,15 +200,6 @@
         self.atom_int(typecode, len(x))
         self.put(x)
 
-    def atom_strlist(self, typecode, tc2, x):
-        self.atom_int(typecode, len(x))
-        atom_str = self.atom_str
-        for item in x:
-            # type(str) seems to be forbidden
-            #if type(item) is not str:
-            #    self.raise_exc('object with wrong type in strlist')
-            atom_str(tc2, item)
-
     def start(self, typecode):
         # type(char) not supported
         self.put(typecode)
@@ -382,16 +372,6 @@
         self.start(typecode)
         return self.get_lng()
 
-    def atom_strlist(self, typecode, tc2):
-        self.start(typecode)
-        lng = self.get_lng()
-        res = [None] * lng
-        idx = 0
-        while idx < lng:
-            res[idx] = self.atom_str(tc2)
-            idx += 1
-        return res
-
     def start(self, typecode):
         tc = self.get1()
         if tc != typecode:
@@ -439,7 +419,6 @@
 
     def get_w_obj(self, allow_null=False):
         space = self.space
-        w_ret = space.w_None # something not None
         tc = self.get1()
         w_ret = self._dispatch[ord(tc)](space, self, tc)
         if w_ret is None and not allow_null:
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -275,9 +275,19 @@
 
     @classmethod
     def parse_op(cls, line):
-        # strip comment
+        # strip comment after '#', but not if it appears inside parentheses
         if '#' in line:
-            line = line[:line.index('#')]
+            nested = 0
+            for i, c in enumerate(line):
+                if c == '(':
+                    nested += 1
+                elif c == ')':
+                    assert nested > 0, "more ')' than '(' in %r" % (line,)
+                    nested -= 1
+                elif c == '#' and nested == 0:
+                    line = line[:i]
+                    break
+        #
         if line.strip() == 'guard_not_invalidated?':
             return 'guard_not_invalidated', None, [], '...', False
         # find the resvar, if any
@@ -314,7 +324,7 @@
         # to repeat it every time
         ticker_check = """
             guard_not_invalidated?
-            ticker0 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
+            ticker0 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
             ticker_cond0 = int_lt(ticker0, 0)
             guard_false(ticker_cond0, descr=...)
         """
@@ -323,9 +333,9 @@
         # this is the ticker check generated if we have threads
         thread_ticker_check = """
             guard_not_invalidated?
-            ticker0 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
-            ticker1 = int_sub(ticker0, _)
-            setfield_raw(ticker_address, ticker1, descr=<FieldS pypysig_long_struct.c_value .*>)
+            ticker0 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
+            ticker1 = int_sub(ticker0, #)
+            setfield_raw(#, ticker1, descr=<FieldS pypysig_long_struct.c_value .*>)
             ticker_cond0 = int_lt(ticker1, 0)
             guard_false(ticker_cond0, descr=...)
         """
@@ -333,7 +343,7 @@
         #
         # this is the ticker check generated in PyFrame.handle_operation_error
         exc_ticker_check = """
-            ticker2 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
+            ticker2 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
             ticker_cond1 = int_lt(ticker2, 0)
             guard_false(ticker_cond1, descr=...)
         """
@@ -351,18 +361,31 @@
 
     @staticmethod
     def as_numeric_const(v1):
+        # returns one of:  ('int', value)  ('float', value)  None
         try:
-            return int(v1)
-        except (ValueError, TypeError):
-            return None
+            return ('int', int(v1))
+        except ValueError:
+            pass
+        if '.' in v1:
+            try:
+                return ('float', float(v1))
+            except ValueError:
+                pass
+        return None
 
     def match_var(self, v1, exp_v2):
         assert v1 != '_'
-        if exp_v2 == '_':
+        if exp_v2 == '_':           # accept anything
             return True
+        if exp_v2 is None:
+            return v1 is None
+        assert exp_v2 != '...'      # bogus use of '...' in the expected code
         n1 = self.as_numeric_const(v1)
+        if exp_v2 == '#':           # accept any (integer or float) number
+            return n1 is not None
         n2 = self.as_numeric_const(exp_v2)
-        if n1 is not None and n2 is not None:
+        if n1 is not None or n2 is not None:
+            # at least one is a number; check that both are, and are equal
             return n1 == n2
         if self.is_const(v1) or self.is_const(exp_v2):
             return v1[:-1].startswith(exp_v2[:-1])
@@ -382,10 +405,13 @@
     def match_op(self, op, (exp_opname, exp_res, exp_args, exp_descr, _)):
         self._assert(op.name == exp_opname, "operation mismatch")
         self.match_var(op.res, exp_res)
-        if exp_args != ['...']:
+        if exp_args[-1:] == ['...']:      # exp_args ends with '...'
+            exp_args = exp_args[:-1]
+            self._assert(len(op.args) >= len(exp_args), "not enough arguments")
+        else:
             self._assert(len(op.args) == len(exp_args), "wrong number of arguments")
-            for arg, exp_arg in zip(op.args, exp_args):
-                self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
+        for arg, exp_arg in zip(op.args, exp_args):
+            self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
         self.match_descr(op.descr, exp_descr)
 
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -158,6 +158,24 @@
         assert match_var('v0', 'V0')
         assert match_var('ConstPtr(ptr0)', '_')
         py.test.raises(AssertionError, "match_var('_', 'v0')")
+        #
+        # numerics
+        assert match_var('1234', '1234')
+        assert not match_var('1234', '1235')
+        assert not match_var('v0', '1234')
+        assert not match_var('1234', 'v0')
+        assert match_var('1234', '#')        # the '#' char matches any number
+        assert not match_var('v0', '#')
+        assert match_var('1234', '_')        # the '_' char matches anything
+        #
+        # float numerics
+        assert match_var('0.000000', '0.0')
+        assert not match_var('0.000000', '0')
+        assert not match_var('0', '0.0')
+        assert not match_var('v0', '0.0')
+        assert not match_var('0.0', 'v0')
+        assert match_var('0.0', '#')
+        assert match_var('0.0', '_')
 
     def test_parse_op(self):
         res = OpMatcher.parse_op("  a =   int_add(  b,  3 ) # foo")
@@ -210,6 +228,19 @@
         """
         assert not self.match(loop, expected)
 
+    def test_dotdotdot_in_operation(self):
+        loop = """
+            [i0, i1]
+            jit_debug(i0, 1, ConstClass(myclass), i1)
+        """
+        assert self.match(loop, "jit_debug(...)")
+        assert self.match(loop, "jit_debug(i0, ...)")
+        assert self.match(loop, "jit_debug(i0, 1, ...)")
+        assert self.match(loop, "jit_debug(i0, 1, _, ...)")
+        assert self.match(loop, "jit_debug(i0, 1, _, i1, ...)")
+        py.test.raises(AssertionError, self.match,
+                       loop, "jit_debug(i0, 1, ..., i1)")
+
     def test_match_descr(self):
         loop = """
             [p0]
@@ -232,7 +263,7 @@
             jump(i4)
         """
         expected = """
-            i1 = int_add(0, 1)
+            i1 = int_add(i0, 1)
             ...
             i4 = int_mul(i1, 1000)
             jump(i4, descr=...)
@@ -249,7 +280,7 @@
             jump(i4, descr=...)
         """
         expected = """
-            i1 = int_add(0, 1)
+            i1 = int_add(i0, 1)
             ...
             _ = int_mul(_, 1000)
             jump(i4, descr=...)
@@ -268,7 +299,7 @@
             jump(i4)
         """
         expected = """
-            i1 = int_add(0, 1)
+            i1 = int_add(i0, 1)
             ...
         """
         assert self.match(loop, expected)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_buffers.py b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_buffers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
@@ -21,7 +21,7 @@
             i65 = getfield_gc(p18, descr=...)
             i67 = int_gt(0, i65)
             guard_false(i67, descr=...)
-            i69 = int_gt(., i65)
+            i69 = int_gt(#, i65)
             guard_true(i69, descr=...)
             --TICK--
         """)
@@ -56,7 +56,7 @@
             guard_false(i99, descr=...)
             i100 = int_lshift(i98, 24)
             i101 = int_or(i97, i100)
-            i102 = getfield_raw(\d+, descr=<FieldS pypysig_long_struct.c_value 0>)
+            i102 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
             i103 = int_lt(i102, 0)
             guard_false(i103, descr=...)
         """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -395,7 +395,7 @@
             setarrayitem_gc(p24, 0, p26, descr=<ArrayP .>)
             setfield_gc(p22, p24, descr=<FieldP .*Arguments.inst_arguments_w .*>)
             }}}
-            p32 = call_may_force(..., p18, p22, descr=<Callr . rr EF=6>)
+            p32 = call_may_force(_, p18, p22, descr=<Callr . rr EF=6>)
             ...
         """)
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -82,7 +82,7 @@
             guard_no_exception(descr=...)
             i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4 OS=4>)
             guard_no_exception(descr=...)
-            i26 = int_and(i23, .*)
+            i26 = int_and(i23, #)
             i27 = int_is_true(i26)
             guard_false(i27, descr=...)
             p28 = getfield_gc(p13, descr=<FieldP dicttable.entries .*>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py
--- a/pypy/module/pypyjit/test_pypy_c/test_math.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_math.py
@@ -21,7 +21,7 @@
             guard_true(i2, descr=...)
             guard_not_invalidated(descr=...)
             f1 = cast_int_to_float(i0)
-            i3 = float_le(f1, 0)
+            i3 = float_le(f1, 0.0)
             guard_false(i3, descr=...)
             f2 = call(ConstClass(log), f1, descr=<Callf . f EF=2>)
             f3 = call(ConstClass(log10), f1, descr=<Callf . f EF=2>)
@@ -56,7 +56,7 @@
             f3 = call(ConstClass(cos), f1, descr=<Callf . f EF=0>)
             f4 = float_sub(f2, f3)
             f5 = float_add(f0, f4)
-            i7 = int_add(i0, f1)
+            i7 = int_add(i0, 1)
             --TICK--
             jump(..., descr=)
         """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -104,7 +104,7 @@
             setarrayitem_gc(p150, 1, 0, descr=<ArrayS .+>)
             setarrayitem_gc(p150, 0, 0, descr=<ArrayS .+>)
             guard_not_invalidated(descr=...)
-            i154 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+            i154 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
             i155 = int_lt(i154, 0)
             guard_false(i155, descr=...)
             p156 = new_with_vtable(...)
@@ -142,7 +142,7 @@
             raw_store(i103, i132, 42.000000, descr=<ArrayF 8>)
             p152 = getfield_gc_pure(p126, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices .+>)
             i153 = int_add(i120, 1)
-            i154 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+            i154 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
             setarrayitem_gc(p152, 1, 0, descr=<ArrayS .+>)
             setarrayitem_gc(p152, 0, 0, descr=<ArrayS .+>)
             i157 = int_lt(i154, 0)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -67,15 +67,15 @@
             i11 = int_lt(i6, i7)
             guard_true(i11, descr=...)
             guard_not_invalidated(descr=...)
-            i13 = int_eq(i6, %d)
+            i13 = int_eq(i6, %d)         # value provided below
             guard_false(i13, descr=...)
-            i15 = int_mod(i6, i8)
-            i17 = int_rshift(i15, %d)
-            i18 = int_and(i8, i17)
+            i15 = int_mod(i6, 10)
+            i17 = int_rshift(i15, %d)    # value provided below
+            i18 = int_and(10, i17)
             i19 = int_add(i15, i18)
             i21 = int_lt(i19, 0)
             guard_false(i21, descr=...)
-            i22 = int_ge(i19, i8)
+            i22 = int_ge(i19, 10)
             guard_false(i22, descr=...)
             i23 = strgetitem(p10, i19)
             p25 = newstr(1)
@@ -83,7 +83,7 @@
             p93 = call(ConstClass(fromstr), p25, 16, descr=<Callr . ri EF=3>)
             guard_no_exception(descr=...)
             i95 = getfield_gc_pure(p93, descr=<FieldS rpython.rlib.rbigint.rbigint.inst_size .*>)
-            i96 = int_gt(i95, .*)
+            i96 = int_gt(i95, #)
             guard_false(i96, descr=...)
             i94 = call(ConstClass(rbigint._toint_helper), p93, descr=<Calli . r EF=3>)
             guard_no_exception(descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -64,7 +64,7 @@
         guard_true(i56, descr=...)
         p57 = force_token()
         setfield_gc(p0, p57, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
-        i58 = call_release_gil(..., i37, 1, descr=<Calli 4 ii EF=6>)
+        i58 = call_release_gil(_, i37, 1, descr=<Calli 4 ii EF=6>)
         guard_not_forced(descr=...)
         guard_no_exception(descr=...)
         i59 = int_is_true(i58)
@@ -72,14 +72,14 @@
         i60 = int_sub(i44, 1)
         p62 = force_token()
         setfield_gc(p0, p62, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
-        i63 = call_release_gil(..., i37, 0, descr=<Calli 4 ii EF=6>)
+        i63 = call_release_gil(_, i37, 0, descr=<Calli 4 ii EF=6>)
         guard_not_forced(descr=...)
         guard_no_exception(descr=...)
         i64 = int_is_true(i63)
         guard_false(i64, descr=...)
         p65 = force_token()
         setfield_gc(p0, p65, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
-        call_release_gil(..., i37, descr=<Callv 0 i EF=6>)
+        call_release_gil(_, i37, descr=<Callv 0 i EF=6>)
         guard_not_forced(descr=...)
         guard_no_exception(descr=...)
         guard_not_invalidated(descr=...)
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -322,8 +322,8 @@
     m.put_int(x.co_stacksize)
     m.put_int(x.co_flags)
     m.atom_str(TYPE_STRING, x.co_code)
-    m.put_tuple_w(TYPE_TUPLE, x.co_consts_w[:])
-    m.atom_strlist(TYPE_TUPLE, TYPE_STRING, [space.str_w(w_name) for w_name in x.co_names_w])
+    m.put_tuple_w(TYPE_TUPLE, x.co_consts_w)
+    m.put_tuple_w(TYPE_TUPLE, x.co_names_w)
     m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_varnames)
     m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_freevars)
     m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_cellvars)
@@ -332,9 +332,8 @@
     m.put_int(x.co_firstlineno)
     m.atom_str(TYPE_STRING, x.co_lnotab)
 
-# helper for unmarshalling string lists of code objects.
-# unfortunately they now can be interned or referenced,
-# so we no longer can handle it in interp_marshal.atom_strlist
+# helper for unmarshalling "tuple of string" objects
+# into rpython-level lists of strings.  Only for code objects.
 
 def unmarshal_str(u):
     w_obj = u.get_w_obj()
diff --git a/rpython/flowspace/bytecode.py b/rpython/flowspace/bytecode.py
--- a/rpython/flowspace/bytecode.py
+++ b/rpython/flowspace/bytecode.py
@@ -81,37 +81,37 @@
         and **varkwarg, if they exist."""
         return self.signature.scope_length()
 
-    def read(self, pos):
+    def read(self, offset):
         """
-        Decode the instruction starting at position ``next_instr``.
+        Decode the instruction starting at position ``offset``.
 
-        Returns (next_instr, opname, oparg).
+        Returns (next_offset, opname, oparg).
         """
         co_code = self.co_code
-        opnum = ord(co_code[pos])
-        next_instr = pos + 1
+        opnum = ord(co_code[offset])
+        next_offset = offset + 1
 
         if opnum >= HAVE_ARGUMENT:
-            lo = ord(co_code[next_instr])
-            hi = ord(co_code[next_instr+1])
-            next_instr += 2
+            lo = ord(co_code[next_offset])
+            hi = ord(co_code[next_offset + 1])
+            next_offset += 2
             oparg = (hi * 256) | lo
         else:
             oparg = 0
 
         while opnum == EXTENDED_ARG:
-            opnum = ord(co_code[next_instr])
+            opnum = ord(co_code[next_offset])
             if opnum < HAVE_ARGUMENT:
                 raise BytecodeCorruption
-            lo = ord(co_code[next_instr+1])
-            hi = ord(co_code[next_instr+2])
-            next_instr += 3
+            lo = ord(co_code[next_offset + 1])
+            hi = ord(co_code[next_offset + 2])
+            next_offset += 3
             oparg = (oparg * 65536) | (hi * 256) | lo
 
         if opnum in opcode.hasjrel:
-            oparg += next_instr
+            oparg += next_offset
         opname = self.opnames[opnum]
-        return next_instr, opname, oparg
+        return next_offset, opname, oparg
 
     @property
     def is_generator(self):
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -29,7 +29,7 @@
         msg = ["\n"]
         msg += map(str, self.args)
         msg += [""]
-        msg += source_lines(self.ctx.graph, None, offset=self.ctx.last_instr)
+        msg += source_lines(self.ctx.graph, None, offset=self.ctx.last_offset)
         return "\n".join(msg)
 
 
@@ -288,7 +288,7 @@
 
         self.init_closure(func.func_closure)
         self.f_lineno = code.co_firstlineno
-        self.last_instr = 0
+        self.last_offset = 0
 
         self.init_locals_stack(code)
 
@@ -359,7 +359,7 @@
         self.locals_stack_w[:len(items_w)] = items_w
         self.dropvaluesuntil(len(items_w))
 
-    def getstate(self, next_pos):
+    def getstate(self, next_offset):
         # getfastscope() can return real None, for undefined locals
         data = self.save_locals_stack()
         if self.last_exception is None:
@@ -369,7 +369,7 @@
             data.append(self.last_exception.w_type)
             data.append(self.last_exception.w_value)
         recursively_flatten(data)
-        return FrameState(data, self.blockstack[:], next_pos)
+        return FrameState(data, self.blockstack[:], next_offset)
 
     def setstate(self, state):
         """ Reset the context to the given frame state. """
@@ -393,7 +393,7 @@
         if getattr(recorder, 'final_state', None) is not None:
             self.mergeblock(recorder.crnt_block, recorder.final_state)
             raise StopFlowing
-        spaceop.offset = self.last_instr
+        spaceop.offset = self.last_offset
         recorder.append(spaceop)
 
     def do_op(self, op):
@@ -424,12 +424,12 @@
 
     def record_block(self, block):
         self.setstate(block.framestate)
-        next_pos = block.framestate.next_instr
+        next_offset = block.framestate.next_offset
         self.recorder = block.make_recorder()
         try:
             while True:
-                next_pos = self.handle_bytecode(next_pos)
-                self.recorder.final_state = self.getstate(next_pos)
+                next_offset = self.handle_bytecode(next_offset)
+                self.recorder.final_state = self.getstate(next_offset)
 
         except RaiseImplicit as e:
             w_exc = e.w_exc
@@ -467,10 +467,10 @@
         self.recorder = None
 
     def mergeblock(self, currentblock, currentstate):
-        next_instr = currentstate.next_instr
+        next_offset = currentstate.next_offset
         # can 'currentstate' be merged with one of the blocks that
         # already exist for this bytecode position?
-        candidates = self.joinpoints.setdefault(next_instr, [])
+        candidates = self.joinpoints.setdefault(next_offset, [])
         for block in candidates:
             newstate = block.framestate.union(currentstate)
             if newstate is not None:
@@ -526,12 +526,12 @@
                     stack_items_w[i] = w_new
                     break
 
-    def handle_bytecode(self, next_instr):
-        self.last_instr = next_instr
-        next_instr, methodname, oparg = self.pycode.read(next_instr)
+    def handle_bytecode(self, next_offset):
+        self.last_offset = next_offset
+        next_offset, methodname, oparg = self.pycode.read(next_offset)
         try:
-            res = getattr(self, methodname)(oparg)
-            return res if res is not None else next_instr
+            offset = getattr(self, methodname)(oparg)
+            return offset if offset is not None else next_offset
         except FlowSignal as signal:
             return self.unroll(signal)
 
@@ -856,14 +856,9 @@
     def WITH_CLEANUP(self, oparg):
         # Note: RPython context managers receive None in lieu of tracebacks
         # and cannot suppress the exception.
-        # This opcode changed a lot between CPython versions
-        if sys.version_info >= (2, 6):
-            unroller = self.popvalue()
-            w_exitfunc = self.popvalue()
-            self.pushvalue(unroller)
-        else:
-            w_exitfunc = self.popvalue()
-            unroller = self.peekvalue(0)
+        unroller = self.popvalue()
+        w_exitfunc = self.popvalue()
+        self.pushvalue(unroller)
 
         if isinstance(unroller, Raise):
             w_exc = unroller.w_exc
diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
--- a/rpython/flowspace/framestate.py
+++ b/rpython/flowspace/framestate.py
@@ -3,10 +3,10 @@
 
 
 class FrameState(object):
-    def __init__(self, mergeable, blocklist, next_instr):
+    def __init__(self, mergeable, blocklist, next_offset):
         self.mergeable = mergeable
         self.blocklist = blocklist
-        self.next_instr = next_instr
+        self.next_offset = next_offset
 
     def copy(self):
         "Make a copy of this state in which all Variables are fresh."
@@ -15,7 +15,7 @@
             if isinstance(w, Variable):
                 w = Variable(w)
             newstate.append(w)
-        return FrameState(newstate, self.blocklist, self.next_instr)
+        return FrameState(newstate, self.blocklist, self.next_offset)
 
     def getvariables(self):
         return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -26,7 +26,7 @@
         # safety check, don't try to compare states with different
         # nonmergeable states
         assert self.blocklist == other.blocklist
-        assert self.next_instr == other.next_instr
+        assert self.next_offset == other.next_offset
         for w1, w2 in zip(self.mergeable, other.mergeable):
             if not (w1 == w2 or (isinstance(w1, Variable) and
                                  isinstance(w2, Variable))):
@@ -44,7 +44,7 @@
                 newstate.append(union(w1, w2))
         except UnionError:
             return None
-        return FrameState(newstate, self.blocklist, self.next_instr)
+        return FrameState(newstate, self.blocklist, self.next_offset)
 
     def getoutputargs(self, targetstate):
         "Return the output arguments needed to link self to targetstate."
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1832,15 +1832,17 @@
             offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
             mc.MOV_br(offset, ebx.value)
 
-        # now we return from the complete frame, which starts from
-        # _call_header_with_stack_check().  The LEA in _call_footer below
-        # throws away most of the frame, including all the PUSHes that we
-        # did just above.
+        # fill in the jf_descr and jf_gcmap fields of the frame according
+        # to which failure we are resuming from.  These are constants
+        # pushed on the stack just before we jump to the current helper,
+        # in generate_quick_failure().
         ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
         ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
         mc.POP_b(ofs2)
         mc.POP_b(ofs)
 
+        # now we return from the complete frame, which starts from
+        # _call_header_with_stack_check().  The _call_footer below does it.
         self._call_footer()
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.failure_recovery_code[exc + 2 * withfloats] = rawstart
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -216,8 +216,8 @@
         # fall-back number.
         "nursery_size": 896*1024,
 
-        # The system page size.  Like obmalloc.c, we assume that it is 4K
-        # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
+        # The system page size.  Like malloc, we assume that it is 4K
+        # for 32-bit systems; unlike malloc, we assume that it is 8K
         # for 64-bit systems, for consistent results.
         "page_size": 1024*WORD,
 
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -174,8 +174,8 @@
         # fall-back number.
         "nursery_size": 896*1024,
 
-        # The system page size.  Like obmalloc.c, we assume that it is 4K
-        # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
+        # The system page size.  Like malloc, we assume that it is 4K
+        # for 32-bit systems; unlike malloc, we assume that it is 8K
         # for 64-bit systems, for consistent results.
         "page_size": 1024*WORD,
 
diff --git a/rpython/memory/gc/minimarktest.py b/rpython/memory/gc/minimarktest.py
--- a/rpython/memory/gc/minimarktest.py
+++ b/rpython/memory/gc/minimarktest.py
@@ -5,7 +5,7 @@
 from rpython.rlib.rarithmetic import LONG_BIT
 
 # For testing, a simple implementation of ArenaCollection.
-# This version could be used together with obmalloc.c, but
+# This version could be used together with malloc, but
 # it requires an extra word per object in the 'all_objects'
 # list.
 
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -461,17 +461,18 @@
                                             annmodel.SomeInteger(nonneg=True)],
                                            annmodel.s_None)
 
-        self.pin_ptr = getfn(GCClass.pin,
-                             [s_gc, SomeAddress()],
-                             annmodel.SomeBool())
+        if GCClass.can_usually_pin_objects:
+            self.pin_ptr = getfn(GCClass.pin,
+                                 [s_gc, SomeAddress()],
+                                 annmodel.SomeBool())
 
-        self.unpin_ptr = getfn(GCClass.unpin,
-                               [s_gc, SomeAddress()],
-                               annmodel.s_None)
+            self.unpin_ptr = getfn(GCClass.unpin,
+                                   [s_gc, SomeAddress()],
+                                   annmodel.s_None)
 
-        self._is_pinned_ptr = getfn(GCClass._is_pinned,
-                                    [s_gc, SomeAddress()],
-                                    annmodel.SomeBool())
+            self._is_pinned_ptr = getfn(GCClass._is_pinned,
+                                        [s_gc, SomeAddress()],
+                                        annmodel.SomeBool())
 
         self.write_barrier_ptr = None
         self.write_barrier_from_array_ptr = None
@@ -1042,6 +1043,10 @@
                                   v_size])
 
     def gct_gc_pin(self, hop):
+        if not hasattr(self, 'pin_ptr'):
+            c_false = rmodel.inputconst(lltype.Bool, False)
+            hop.genop("same_as", [c_false], resultvar=hop.spaceop.result)
+            return
         op = hop.spaceop
         v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
             resulttype=llmemory.Address)
@@ -1049,6 +1054,8 @@
                   resultvar=op.result)
 
     def gct_gc_unpin(self, hop):
+        if not hasattr(self, 'unpin_ptr'):
+            return
         op = hop.spaceop
         v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
             resulttype=llmemory.Address)
@@ -1056,6 +1063,10 @@
                   resultvar=op.result)
 
     def gct_gc__is_pinned(self, hop):
+        if not hasattr(self, '_is_pinned_ptr'):
+            c_false = rmodel.inputconst(lltype.Bool, False)
+            hop.genop("same_as", [c_false], resultvar=hop.spaceop.result)
+            return
         op = hop.spaceop
         v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
             resulttype=llmemory.Address)
diff --git a/rpython/rlib/rweakref.py b/rpython/rlib/rweakref.py
--- a/rpython/rlib/rweakref.py
+++ b/rpython/rlib/rweakref.py
@@ -105,7 +105,7 @@
                                                rtyper.getrepr(self.s_key))
 
     def rtyper_makekey(self):
-        return self.__class__,
+        return self.__class__, self.s_key.rtyper_makekey(), self.valueclassdef
 
     def method_get(self, s_key):
         return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
@@ -165,7 +165,7 @@
         return _rweakkeydict.WeakKeyDictRepr(rtyper)
 
     def rtyper_makekey(self):
-        return self.__class__,
+        return self.__class__, self.keyclassdef, self.valueclassdef
 
     def method_get(self, s_key):
         assert isinstance(s_key, annmodel.SomeInstance)
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -311,7 +311,7 @@
     assert isinstance(lst, list)
     found = False
     for family, socktype, protocol, canonname, addr in lst:
-        if addr.get_host() == '140.211.10.69':
+        if addr.get_host() == '104.130.43.121':
             found = True
     result[i] += found
 
diff --git a/rpython/rlib/test/test_rweakvaldict.py b/rpython/rlib/test/test_rweakvaldict.py
--- a/rpython/rlib/test/test_rweakvaldict.py
+++ b/rpython/rlib/test/test_rweakvaldict.py
@@ -144,3 +144,13 @@
             d = RWeakValueDictionary(str, Y)
         d.set("x", X())
     py.test.raises(Exception, interpret, g, [1])
+
+
+def test_bogus_makekey():
+    class X: pass
+    class Y: pass
+    def g():
+        X(); Y()
+        RWeakValueDictionary(str, X).get("foobar")
+        RWeakValueDictionary(int, Y).get(42)
+    interpret(g, [])
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -100,7 +100,6 @@
     def test_string_reverse(self):
         c_source = py.code.Source("""
         #include <string.h>
-        #include <src/allocator.h>
         #include <src/mem.h>
 
         char *f(char* arg)
diff --git a/rpython/rtyper/normalizecalls.py b/rpython/rtyper/normalizecalls.py
--- a/rpython/rtyper/normalizecalls.py
+++ b/rpython/rtyper/normalizecalls.py
@@ -298,12 +298,16 @@
 
 # ____________________________________________________________
 
+class TooLateForNewSubclass(Exception):
+    pass
+
 class TotalOrderSymbolic(ComputedIntSymbolic):
 
     def __init__(self, orderwitness, peers):
         self.orderwitness = orderwitness
         self.peers = peers
         self.value = None
+        self._with_subclasses = None    # unknown
         peers.append(self)
 
     def __cmp__(self, other):
@@ -320,12 +324,34 @@
     def __rsub__(self, other):
         return other - self.compute_fn()
 
+    def check_any_subclass_in_peer_list(self, i):
+        # check if the next peer, in order, is or not the end
+        # marker for this start marker
+        assert self.peers[i] is self
+        return self.peers[i + 1].orderwitness != self.orderwitness + [MAX]
+
+    def number_with_subclasses(self):
+        # Return True or False depending on whether this is the
+        # subclassrange_min corresponding to a class which has subclasses
+        # or not.  If this is called and returns False, then adding later
+        # new subclasses will crash in compute_fn().
+        if self._with_subclasses is None:     # unknown so far
+            self.peers.sort()
+            i = self.peers.index(self)
+            self._with_subclasses = self.check_any_subclass_in_peer_list(i)
+        return self._with_subclasses
+
     def compute_fn(self):
         if self.value is None:
             self.peers.sort()
             for i, peer in enumerate(self.peers):
                 assert peer.value is None or peer.value == i
                 peer.value = i
+                #
+                if peer._with_subclasses is False:
+                    if peer.check_any_subclass_in_peer_list(i):
+                        raise TooLateForNewSubclass
+                #
             assert self.value is not None
         return self.value
 
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -1007,14 +1007,11 @@
         v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
         if isinstance(v_cls, Constant):
             cls = v_cls.value
-            # XXX re-implement the following optimization
-            #if cls.subclassrange_max == cls.subclassrange_min:
-            #    # a class with no subclass
-            #    return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls)
-            #else:
-            minid = hop.inputconst(Signed, cls.subclassrange_min)
-            maxid = hop.inputconst(Signed, cls.subclassrange_max)
-            return hop.gendirectcall(ll_isinstance_const, v_obj, minid, maxid)
+            llf, llf_nonnull = make_ll_isinstance(self.rtyper, cls)
+            if hop.args_s[0].can_be_None:
+                return hop.gendirectcall(llf, v_obj)
+            else:
+                return hop.gendirectcall(llf_nonnull, v_obj)
         else:
             return hop.gendirectcall(ll_isinstance, v_obj, v_cls)
 
@@ -1128,16 +1125,26 @@
     obj_cls = obj.typeptr
     return ll_issubclass(obj_cls, cls)
 
-def ll_isinstance_const(obj, minid, maxid):
-    if not obj:
-        return False
-    return ll_issubclass_const(obj.typeptr, minid, maxid)
-
-def ll_isinstance_exact(obj, cls):
-    if not obj:
-        return False
-    obj_cls = obj.typeptr
-    return obj_cls == cls
+def make_ll_isinstance(rtyper, cls):
+    try:
+        return rtyper.isinstance_helpers[cls._obj]
+    except KeyError:
+        minid = cls.subclassrange_min
+        maxid = cls.subclassrange_max
+        if minid.number_with_subclasses():
+            def ll_isinstance_const_nonnull(obj):
+                objid = obj.typeptr.subclassrange_min
+                return llop.int_between(Bool, minid, objid, maxid)
+        else:
+            def ll_isinstance_const_nonnull(obj):
+                return obj.typeptr == cls
+        def ll_isinstance_const(obj):
+            if not obj:
+                return False
+            return ll_isinstance_const_nonnull(obj)
+        result = (ll_isinstance_const, ll_isinstance_const_nonnull)
+        rtyper.isinstance_helpers[cls._obj] = result
+        return result
 
 def ll_runtime_type_info(obj):
     return obj.typeptr.rtti
diff --git a/rpython/rtyper/rtyper.py b/rpython/rtyper/rtyper.py
--- a/rpython/rtyper/rtyper.py
+++ b/rpython/rtyper/rtyper.py
@@ -59,6 +59,7 @@
         self.typererror_count = 0
         # make the primitive_to_repr constant mapping
         self.primitive_to_repr = {}
+        self.isinstance_helpers = {}
         self.exceptiondata = ExceptionData(self)
         self.custom_trace_funcs = []
 
diff --git a/rpython/rtyper/test/test_normalizecalls.py b/rpython/rtyper/test/test_normalizecalls.py
--- a/rpython/rtyper/test/test_normalizecalls.py
+++ b/rpython/rtyper/test/test_normalizecalls.py
@@ -6,6 +6,7 @@
 from rpython.rtyper.test.test_llinterp import interpret
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.normalizecalls import TotalOrderSymbolic, MAX
+from rpython.rtyper.normalizecalls import TooLateForNewSubclass
 
 
 def test_TotalOrderSymbolic():
@@ -21,6 +22,49 @@
     assert t1 <= 5
     assert t1.value == 0
 
+def test_TotalOrderSymbolic_with_subclasses():
+    lst = []
+    t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+    t1 = TotalOrderSymbolic([3, 4], lst)
+    t2 = TotalOrderSymbolic([3, 4, 2], lst)
+    t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+    assert t1.number_with_subclasses()
+    assert not t2.number_with_subclasses()
+    assert [t.compute_fn() for t in [t1, t2, t3, t4]] == range(4)
+    #
+    lst = []
+    t1 = TotalOrderSymbolic([3, 4], lst)
+    t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+    t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+    t2 = TotalOrderSymbolic([3, 4, 2], lst)
+    assert not t2.number_with_subclasses()
+    assert t1.number_with_subclasses()
+    assert [t.compute_fn() for t in [t1, t2, t3, t4]] == range(4)
+    #
+    lst = []
+    t1 = TotalOrderSymbolic([3, 4], lst)
+    t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+    assert not t1.number_with_subclasses()
+    t2 = TotalOrderSymbolic([3, 4, 2], lst)
+    t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+    py.test.raises(TooLateForNewSubclass, t2.compute_fn)
+    #
+    lst = []
+    t1 = TotalOrderSymbolic([3, 4], lst)
+    t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+    assert not t1.number_with_subclasses()
+    t2 = TotalOrderSymbolic([1], lst)
+    t3 = TotalOrderSymbolic([1, MAX], lst)
+    assert [t.compute_fn() for t in [t2, t3, t1, t4]] == range(4)
+    #
+    lst = []
+    t1 = TotalOrderSymbolic([3, 4], lst)
+    t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+    assert not t1.number_with_subclasses()
+    t2 = TotalOrderSymbolic([6], lst)
+    t3 = TotalOrderSymbolic([6, MAX], lst)
+    assert [t.compute_fn() for t in [t1, t4, t2, t3]] == range(4)
+
 # ____________________________________________________________
 
 class TestNormalize(object):
diff --git a/rpython/tool/jitlogparser/parser.py b/rpython/tool/jitlogparser/parser.py
--- a/rpython/tool/jitlogparser/parser.py
+++ b/rpython/tool/jitlogparser/parser.py
@@ -216,7 +216,7 @@
     line_starts_here = property(getline_starts_here)
 
     def __repr__(self):
-        return "[%s]" % ", ".join([repr(op) for op in self.operations])
+        return "[%s\n]" % "\n    ".join([repr(op) for op in self.operations])
 
     def pretty_print(self, out):
         pass
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -405,8 +405,6 @@
             ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" debug_target'),
             ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" debug_target'),
             ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DPYPY_USE_TRIVIAL_MALLOC" debug_target'),
-            ('no_obmalloc', '', '$(MAKE) CFLAGS="-g -O2 -DRPY_ASSERT -DPYPY_NO_OBMALLOC" $(TARGET)'),
-            ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DPYPY_USE_LINUXMEMCHK" debug_target'),
             ('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET)'),
             ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
             ('lldebug0','', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -O0 -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
@@ -762,7 +760,6 @@
     srcdir = py.path.local(__file__).join('..', 'src')
     files = [
         srcdir / 'entrypoint.c',       # ifdef PYPY_STANDALONE
-        srcdir / 'allocator.c',        # ifdef PYPY_STANDALONE
         srcdir / 'mem.c',
         srcdir / 'exception.c',
         srcdir / 'rtyper.c',           # ifdef HAVE_RTYPER
diff --git a/rpython/translator/c/src/allocator.c b/rpython/translator/c/src/allocator.c
deleted file mode 100644
--- a/rpython/translator/c/src/allocator.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* allocation functions */
-#include "common_header.h"
-#ifdef PYPY_STANDALONE
-#include <stdlib.h>
-
-#if defined(PYPY_USE_TRIVIAL_MALLOC)
-  void *PyObject_Malloc(size_t n) { return malloc(n); }
-  void *PyObject_Realloc(void *p, size_t n) { return realloc(p, n); }
-  void PyObject_Free(void *p) { if (p) { *((int*)p) = 0xDDDDDDDD; } free(p); }
-
-#elif defined(PYPY_USE_LINUXMEMCHK)
-#  include "linuxmemchk.c"
-
-#elif defined(PYPY_NO_OBMALLOC)
-  void *PyObject_Malloc(size_t n) { return malloc(n); }
-  void *PyObject_Realloc(void *p, size_t n) { return realloc(p, n); }
-  void PyObject_Free(void *p) { free(p); }
-
-#else
-#  ifndef WITH_PYMALLOC
-#    define WITH_PYMALLOC
-#  endif
-/* The same obmalloc as CPython */
-#  include "src/obmalloc.c"
-
-#endif
-#elif defined _MSC_VER
-/* link will fail without some kind of definition for the functions */  
-  void *PyObject_Malloc(size_t n) { return NULL; }
-  void *PyObject_Realloc(void *p, size_t n) { return NULL; }
-  void PyObject_Free(void *p) {  }
-
-#endif  /* PYPY_STANDALONE */
diff --git a/rpython/translator/c/src/allocator.h b/rpython/translator/c/src/allocator.h
deleted file mode 100644
--- a/rpython/translator/c/src/allocator.h
+++ /dev/null
@@ -1,4 +0,0 @@
-/* allocation functions prototypes */
-RPY_EXTERN void *PyObject_Malloc(size_t n);
-RPY_EXTERN void *PyObject_Realloc(void *p, size_t n);
-RPY_EXTERN void PyObject_Free(void *p);
diff --git a/rpython/translator/c/src/g_include.h b/rpython/translator/c/src/g_include.h
--- a/rpython/translator/c/src/g_include.h
+++ b/rpython/translator/c/src/g_include.h
@@ -33,7 +33,6 @@
 #  include "src/debug_traceback.h"
 #endif
 
-#  include "src/allocator.h"
 #ifdef PYPY_STANDALONE
 #  include "src/entrypoint.h"
 #endif
diff --git a/rpython/translator/c/src/linuxmemchk.c b/rpython/translator/c/src/linuxmemchk.c
deleted file mode 100644
--- a/rpython/translator/c/src/linuxmemchk.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* custom checking allocators a la Electric Fence */
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define PAGESIZE 4096
-#ifndef MALLOC_BIGBUFFER
-# define MALLOC_BIGBUFFER   (PAGESIZE*32768)   /* 128MB */
-#endif
-
-
-struct _alloc_s {
-  void* ptr;
-  int npages;
-};
-static void* _na_start = NULL;
-static char* _na_cur;
-
-static void _na_assert(int x, char* msg)
-{
-  if (!x)
-    {
-      fprintf(stderr, "linuxmemchk: failed assertion: %s\n", msg);
-      abort();
-    }
-}
-
-static struct _alloc_s* _na_find(void* data)
-{
-  int err;
-  long data1;
-  struct _alloc_s* s;
-  _na_assert(_na_start+PAGESIZE <= data &&
-             data < _na_start+MALLOC_BIGBUFFER-PAGESIZE,
-             "corrupted na_start");
-  data1 = (long) data;
-  data1 &= ~(PAGESIZE-1);
-  data1 -= PAGESIZE;
-  err = mprotect((void*) data1, PAGESIZE, PROT_READ|PROT_WRITE);
-  _na_assert(!err, "mprotect[1] failed");
-  s = (struct _alloc_s*) data1;
-  _na_assert(s->npages > 0, "corrupted s->npages");
-  return s;
-}
-
-void* PyObject_Malloc(size_t size)
-{
-  int err, npages = (size + PAGESIZE-1) / PAGESIZE + 1;
-  struct _alloc_s* s;
-  char* data;
-  if (_na_start == NULL)
-    {
-      _na_start = mmap(NULL, MALLOC_BIGBUFFER, PROT_NONE,
-                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-      _na_assert(_na_start != MAP_FAILED, "initial mmap failed");
-      _na_cur = (char*) _na_start;
-    }
-  s = (struct _alloc_s*) _na_cur;
-  _na_cur += npages * PAGESIZE;
-  if (_na_cur >= ((char*) _na_start) + MALLOC_BIGBUFFER)
-    {
-      fprintf(stderr, "linuxmemchk.c: Nothing wrong so far, but we are running out\nlinuxmemchk.c: of mmap'ed memory.  Increase MALLOC_BIGBUFFER.\n");
-      abort();
-    }
-  err = mprotect(s, npages * PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC);
-  _na_assert(!err, "mprotect[2] failed");
-  s->ptr = data = _na_cur - /*((size+3)&~3)*/ size;
-  s->npages = npages;
-  err = mprotect(s, PAGESIZE, PROT_NONE);
-  _na_assert(!err, "mprotect[3] failed");
-  return data;
-}
-
-void PyObject_Free(void* data)
-{
-  int err, npages;
-  struct _alloc_s* s;
-  if (data == NULL)
-    return;
-  s = _na_find(data);
-  _na_assert(s->ptr == data, "free got a pointer not returned by malloc");
-  npages = s->npages;
-  s->npages = 0;
-  err = mprotect(s, npages * PAGESIZE, PROT_NONE);
-  _na_assert(!err, "mprotect[4] failed");
-}
-
-void* PyObject_Realloc(void* data, size_t nsize)
-{
-  size_t size;
-  struct _alloc_s* s = _na_find(data);
-  void* ndata = PyObject_Malloc(nsize);
-
-  _na_assert(s->ptr == data, "realloc got a pointer not returned by malloc");
-  size = ((char*)s) + s->npages * PAGESIZE - (char*)data;
-  memcpy(ndata, data, size<nsize ? size : nsize);
-  PyObject_Free(data);
-  return ndata;
-}
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -9,13 +9,13 @@
 
 
 #define OP_RAW_MALLOC(size, r, restype)  {				\
-	r = (restype) PyObject_Malloc(size);				\
+	r = (restype) malloc(size);				\
 	if (r != NULL) {						\
 	    COUNT_MALLOC;						\
 	}								\
     }
 
-#define OP_RAW_FREE(p, r) PyObject_Free(p); COUNT_FREE;
+#define OP_RAW_FREE(p, r) free(p); COUNT_FREE;
 
 #define OP_RAW_MEMCLEAR(p, size, r) memset((void*)p, 0, size)
 #define OP_RAW_MEMSET(p, byte, size, r) memset((void*)p, byte, size)
diff --git a/rpython/translator/c/src/obmalloc.c b/rpython/translator/c/src/obmalloc.c
deleted file mode 100644
--- a/rpython/translator/c/src/obmalloc.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-
-#ifdef WITH_PYMALLOC
-
-#include <string.h>
-#include <assert.h>
-
-/* An object allocator for Python.
-
-   Here is an introduction to the layers of the Python memory architecture,
-   showing where the object allocator is actually used (layer +2), It is
-   called for every object allocation and deallocation (PyObject_New/Del),
-   unless the object-specific allocators implement a proprietary allocation
-   scheme (ex.: ints use a simple free list). This is also the place where
-   the cyclic garbage collector operates selectively on container objects.
-
-
-        Object-specific allocators
-    _____   ______   ______       ________
-   [ int ] [ dict ] [ list ] ... [ string ]       Python core         |
-+3 | <----- Object-specific memory -----> | <-- Non-object memory --> |
-    _______________________________       |                           |
-   [   Python's object allocator   ]      |                           |
-+2 | ####### Object memory ####### | <------ Internal buffers ------> |
-    ______________________________________________________________    |
-   [          Python's raw memory allocator (PyMem_ API)          ]   |
-+1 | <----- Python memory (under PyMem manager's control) ------> |   |
-    __________________________________________________________________
-   [    Underlying general-purpose allocator (ex: C library malloc)   ]
- 0 | <------ Virtual memory allocated for the python process -------> |
-
-   =========================================================================
-    _______________________________________________________________________
-   [                OS-specific Virtual Memory Manager (VMM)               ]
--1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |
-    __________________________________   __________________________________
-   [                                  ] [                                  ]
--2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |
-
-*/
-/*==========================================================================*/
-
-/* A fast, special-purpose memory allocator for small blocks, to be used
-   on top of a general-purpose malloc -- heavily based on previous art. */
-
-/* Vladimir Marangozov -- August 2000 */
-
-/*
- * "Memory management is where the rubber meets the road -- if we do the wrong
- * thing at any level, the results will not be good. And if we don't make the
- * levels work well together, we are in serious trouble." (1)
- *
- * (1) Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
- *    "Dynamic Storage Allocation: A Survey and Critical Review",
- *    in Proc. 1995 Int'l. Workshop on Memory Management, September 1995.
- */
-


More information about the pypy-commit mailing list