[pypy-commit] pypy remove-list-smm-2: hg merge default

Manuel Jacob noreply at buildbot.pypy.org
Sun May 19 13:56:46 CEST 2013


Author: Manuel Jacob
Branch: remove-list-smm-2
Changeset: r64323:79cd4b4f08fc
Date: 2013-05-19 13:54 +0200
http://bitbucket.org/pypy/pypy/changeset/79cd4b4f08fc/

Log:	hg merge default

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -121,12 +121,10 @@
                     __import__(name)
             except (ImportError, CompilationError, py.test.skip.Exception), e:
                 errcls = e.__class__.__name__
-                config.add_warning(
+                raise Exception(
                     "The module %r is disabled\n" % (modname,) +
                     "because importing %s raised %s\n" % (name, errcls) +
                     str(e))
-                raise ConflictConfigError("--withmod-%s: %s" % (modname,
-                                                                errcls))
         return validator
     else:
         return None
diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -339,8 +339,9 @@
 
 + methods and other class attributes do not change after startup
 + single inheritance is fully supported
-+ simple mixins work too, but the mixed in class needs a ``_mixin_ = True``
-  class attribute
++ simple mixins somewhat work too, but the mixed in class needs a
+  ``_mixin_ = True`` class attribute. isinstance checks against the
+  mixin type will fail when translated.
 
 + classes are first-class objects too
 
diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst
--- a/pypy/doc/how-to-contribute.rst
+++ b/pypy/doc/how-to-contribute.rst
@@ -28,7 +28,8 @@
 Layers
 ------
 
-PyPy has layers. Those layers help us keep the respective parts separated enough
+PyPy has layers. Just like Ogres or onions.
+Those layers help us keep the respective parts separated enough
 to be worked on independently and make the complexity manageable. This is,
 again, just a sanity requirement for such a complex project. For example writing
 a new optimization for the JIT usually does **not** involve touching a Python
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -10,6 +10,8 @@
 from rpython.config.config import ConflictConfigError
 from pypy.tool.option import make_objspace
 from pypy.conftest import pypydir
+from rpython.rlib import rthread
+from pypy.module.thread import os_thread
 
 thisdir = py.path.local(__file__).dirpath()
 
@@ -120,6 +122,15 @@
         source = rffi.charp2str(ll_source)
         return _pypy_execute_source(source)
 
+    @entrypoint('main', [], c_name='pypy_init_threads')
+    def pypy_init_threads():
+        os_thread.setup_threads(space)
+        rffi.aroundstate.before()
+
+    @entrypoint('main', [], c_name='pypy_thread_attach')
+    def pypy_thread_attach():
+        rthread.gc_thread_start()
+
     w_globals = space.newdict()
     space.setitem(w_globals, space.wrap('__builtins__'),
                   space.builtin_modules['__builtin__'])
@@ -137,6 +148,8 @@
         return 0
 
     return entry_point, {'pypy_execute_source': pypy_execute_source,
+                         'pypy_init_threads': pypy_init_threads,
+                         'pypy_thread_attach': pypy_thread_attach,
                          'pypy_setup_home': pypy_setup_home}
 
 def call_finish(space):
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -853,9 +853,10 @@
             self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup, True)
             if i < (ops_count - 1):
                 comp.comparators[i].walkabout(self)
-        comp.comparators[-1].walkabout(self)
-        last_kind = compare_operations(comp.ops[-1])
-        self.emit_op_arg(ops.COMPARE_OP, last_kind)
+        last_op, last_comparator = comp.ops[-1], comp.comparators[-1]
+        if not self._optimize_comparator(last_op, last_comparator):
+            last_comparator.walkabout(self)
+        self.emit_op_arg(ops.COMPARE_OP, compare_operations(last_op))
         if ops_count > 1:
             end = self.new_block()
             self.emit_jump(ops.JUMP_FORWARD, end)
@@ -864,6 +865,37 @@
             self.emit_op(ops.POP_TOP)
             self.use_next_block(end)
 
+    def _optimize_comparator(self, op, node):
+        """Fold lists/sets of constants in the context of "in"/"not in".
+
+        lists are folded into tuples, sets into frozensets, otherwise
+        returns False
+        """
+        if op in (ast.In, ast.NotIn):
+            is_list = isinstance(node, ast.List)
+            if is_list or isinstance(node, ast.Set):
+                w_const = self._tuple_of_consts(node.elts)
+                if w_const is not None:
+                    if not is_list:
+                        from pypy.objspace.std.setobject import (
+                            W_FrozensetObject)
+                        w_const = W_FrozensetObject(self.space, w_const)
+                    self.load_const(w_const)
+                    return True
+        return False
+
+    def _tuple_of_consts(self, elts):
+        """Return a tuple of consts from elts if possible, or None"""
+        count = len(elts) if elts is not None else 0
+        consts_w = [None] * count
+        for i in range(count):
+            w_value = elts[i].as_constant()
+            if w_value is None:
+                # Not all constants
+                return None
+            consts_w[i] = w_value
+        return self.space.newtuple(consts_w)
+
     def visit_IfExp(self, ifexp):
         self.update_position(ifexp.lineno)
         end = self.new_block()
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -973,3 +973,30 @@
         counts = self.count_instructions(source3)
         assert counts[ops.BUILD_LIST] == 1
         assert ops.BUILD_LIST_FROM_ARG not in counts
+
+    def test_folding_of_list_constants(self):
+        for source in (
+            # in/not in constants with BUILD_LIST should be folded to a tuple:
+            'a in [1,2,3]',
+            'a not in ["a","b","c"]',
+            'a in [None, 1, None]',
+            'a not in [(1, 2), 3, 4]',
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BUILD_LIST not in counts
+            assert ops.LOAD_CONST in counts
+
+    def test_folding_of_set_constants(self):
+        for source in (
+            # in/not in constants with BUILD_SET should be folded to a frozenset:
+            'a in {1,2,3}',
+            'a not in {"a","b","c"}',
+            'a in {None, 1, None}',
+            'a not in {(1, 2), 3, 4}',
+            'a in {1, 2, 3, 3, 2, 1}',
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BUILD_SET not in counts
+            assert ops.LOAD_CONST in counts
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -903,24 +903,35 @@
         expected_path = [str(prefix.join(subdir).ensure(dir=1))
                          for subdir in ('lib_pypy',
                                         'lib-python/%s' % cpy_ver)]
+        # an empty directory from where we can't find the stdlib
+        tmp_dir = str(udir.join('tmp').ensure(dir=1))
 
         self.w_goal_dir = self.space.wrap(goal_dir)
         self.w_fake_exe = self.space.wrap(str(fake_exe))
         self.w_expected_path = self.space.wrap(expected_path)
         self.w_trunkdir = self.space.wrap(os.path.dirname(pypydir))
 
+        self.w_tmp_dir = self.space.wrap(tmp_dir)
+
         foo_py = prefix.join('foo.py').write("pass")
         self.w_foo_py = self.space.wrap(str(foo_py))
 
     def test_setup_bootstrap_path(self):
-        import sys
+        # Check how sys.path is handled depending on if we can find a copy of
+        # the stdlib in setup_bootstrap_path.
+        import sys, os
         old_sys_path = sys.path[:]
+        old_cwd = os.getcwd()
+
         sys.path.append(self.goal_dir)
+        # make sure cwd does not contain a stdlib
+        os.chdir(self.tmp_dir)
+        tmp_pypy_c = os.path.join(self.tmp_dir, 'pypy-c')
         try:
             import app_main
-            app_main.setup_bootstrap_path('/tmp/pypy-c') # stdlib not found
+            app_main.setup_bootstrap_path(tmp_pypy_c)  # stdlib not found
             assert sys.executable == ''
-            assert sys.path == old_sys_path
+            assert sys.path == old_sys_path + [self.goal_dir]
 
             app_main.setup_bootstrap_path(self.fake_exe)
             assert sys.executable == self.fake_exe
@@ -933,6 +944,7 @@
             assert newpath[:len(self.expected_path)] == self.expected_path
         finally:
             sys.path[:] = old_sys_path
+            os.chdir(old_cwd)
 
     def test_trunk_can_be_prefix(self):
         import sys
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
@@ -936,6 +936,21 @@
         output = s.getvalue()
         assert "LOAD_GLOBAL" not in output
 
+    def test_folding_of_list_constants(self):
+        source = 'a in [1, 2, 3]'
+        co = compile(source, '', 'exec')
+        i = co.co_consts.index((1, 2, 3))
+        assert i > -1
+        assert isinstance(co.co_consts[i], tuple)
+
+    def test_folding_of_set_constants(self):
+        source = 'a in {1, 2, 3}'
+        co = compile(source, '', 'exec')
+        i = co.co_consts.index(set([1, 2, 3]))
+        assert i > -1
+        assert isinstance(co.co_consts[i], frozenset)
+
+
 class AppTestCallMethod(object):
     spaceconfig = {'objspace.opcodes.CALL_METHOD': True}
         
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -1,15 +1,16 @@
-from pypy.interpreter import gateway
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.gateway import (
+    WrappedDefault, applevel, interp2app, unwrap_spec)
 from pypy.interpreter.mixedmodule import MixedModule
 from pypy.interpreter.signature import Signature
 from pypy.objspace.std.stdtypedef import StdTypeDef
 from pypy.objspace.std.util import negate
 
-from rpython.rlib import rerased, jit
+from rpython.rlib import jit, rerased
 from rpython.rlib.debug import mark_dict_non_null
-from rpython.rlib.objectmodel import r_dict, specialize, newlist_hint
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.rlib.objectmodel import newlist_hint, r_dict, specialize
+from rpython.tool.sourcetools import func_renamer, func_with_new_name
 
 
 UNROLL_CUTOFF = 5
@@ -19,7 +20,7 @@
     return space.is_w(space.type(w_key), space.w_str)
 
 def _never_equal_to_string(space, w_lookup_type):
-    """ Handles the case of a non string key lookup.
+    """Handles the case of a non string key lookup.
     Types that have a sane hash/eq function should allow us to return True
     directly to signal that the key is not in the dict in any case.
     XXX The types should provide such a flag. """
@@ -33,7 +34,7 @@
 
 @specialize.call_location()
 def w_dict_unrolling_heuristic(w_dct):
-    """ In which cases iterating over dict items can be unrolled.
+    """In which cases iterating over dict items can be unrolled.
     Note that w_dct is an instance of W_DictMultiObject, not necesarilly
     an actual dict
     """
@@ -44,8 +45,8 @@
 class W_DictMultiObject(W_Root):
     @staticmethod
     def allocate_and_init_instance(space, w_type=None, module=False,
-                                   instance=False, strdict=False, kwargs=False):
-
+                                   instance=False, strdict=False,
+                                   kwargs=False):
         if space.config.objspace.std.withcelldict and module:
             from pypy.objspace.std.celldict import ModuleDictStrategy
             assert w_type is None
@@ -55,11 +56,9 @@
         elif space.config.objspace.std.withmapdict and instance:
             from pypy.objspace.std.mapdict import MapDictStrategy
             strategy = space.fromcache(MapDictStrategy)
-
         elif instance or strdict or module:
             assert w_type is None
             strategy = space.fromcache(StringDictStrategy)
-
         elif kwargs:
             assert w_type is None
             from pypy.objspace.std.kwargsdict import EmptyKwargsDictStrategy
@@ -80,7 +79,7 @@
         self.dstorage = storage
 
     def __repr__(w_self):
-        """ representation for debugging purposes """
+        """representation for debugging purposes"""
         return "%s(%s)" % (w_self.__class__.__name__, w_self.strategy)
 
     def unwrap(w_dict, space):
@@ -93,12 +92,10 @@
 
     def missing_method(w_dict, space, w_key):
         if not space.is_w(space.type(w_dict), space.w_dict):
-            w_missing = space.lookup(w_dict, "__missing__")
-            if w_missing is None:
-                return None
-            return space.get_and_call_function(w_missing, w_dict, w_key)
-        else:
-            return None
+            w_missing = space.lookup(w_dict, '__missing__')
+            if w_missing is not None:
+                return space.get_and_call_function(w_missing, w_dict, w_key)
+        return None
 
     def initialize_content(w_self, list_pairs_w):
         for w_k, w_v in list_pairs_w:
@@ -151,7 +148,7 @@
         if self.length() != w_other.length():
             return space.w_False
         iteratorimplementation = self.iteritems()
-        while 1:
+        while True:
             w_key, w_val = iteratorimplementation.next_item()
             if w_key is None:
                 break
@@ -228,7 +225,8 @@
             space.raise_key_error(w_key)
 
     def descr_reversed(self, space):
-        raise OperationError(space.w_TypeError, space.wrap('argument to reversed() must be a sequence'))
+        raise OperationError(space.w_TypeError, space.wrap(
+                'argument to reversed() must be a sequence'))
 
     def descr_copy(self, space):
         """D.copy() -> a shallow copy of D"""
@@ -280,16 +278,13 @@
         """D.clear() -> None.  Remove all items from D."""
         self.clear()
 
-    @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+    @unwrap_spec(w_default=WrappedDefault(None))
     def descr_get(self, space, w_key, w_default):
         """D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None."""
         w_value = self.getitem(w_key)
-        if w_value is not None:
-            return w_value
-        else:
-            return w_default
+        return w_value if w_value is not None else w_default
 
-    @gateway.unwrap_spec(defaults_w='args_w')
+    @unwrap_spec(defaults_w='args_w')
     def descr_pop(self, space, w_key, defaults_w):
         """D.pop(k[,d]) -> v, remove specified key and return the
         corresponding value\nIf key is not found, d is returned if given,
@@ -320,7 +315,7 @@
                                  space.wrap("popitem(): dictionary is empty"))
         return space.newtuple([w_key, w_value])
 
-    @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+    @unwrap_spec(w_default=WrappedDefault(None))
     def descr_setdefault(self, space, w_key, w_default):
         """D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"""
         return self.setdefault(w_key, w_default)
@@ -352,7 +347,7 @@
 _add_indirections()
 
 
-app = gateway.applevel('''
+app = applevel('''
     def dictrepr(currently_in_repr, d):
         if len(d) == 0:
             return "{}"
@@ -388,46 +383,46 @@
         d[k] = v
 dict(**kwargs) -> new dictionary initialized with the name=value pairs
     in the keyword argument list.  For example:  dict(one=1, two=2)''',
-    __new__ = gateway.interp2app(W_DictMultiObject.descr_new),
-    fromkeys = gateway.interp2app(W_DictMultiObject.descr_fromkeys,
-                                  as_classmethod=True),
+    __new__ = interp2app(W_DictMultiObject.descr_new),
+    fromkeys = interp2app(W_DictMultiObject.descr_fromkeys,
+                          as_classmethod=True),
     __hash__ = None,
-    __repr__ = gateway.interp2app(W_DictMultiObject.descr_repr),
-    __init__ = gateway.interp2app(W_DictMultiObject.descr_init),
+    __repr__ = interp2app(W_DictMultiObject.descr_repr),
+    __init__ = interp2app(W_DictMultiObject.descr_init),
 
-    __eq__ = gateway.interp2app(W_DictMultiObject.descr_eq),
-    __ne__ = gateway.interp2app(W_DictMultiObject.descr_ne),
-    __lt__ = gateway.interp2app(W_DictMultiObject.descr_lt),
-    __le__ = gateway.interp2app(W_DictMultiObject.descr_le),
-    __gt__ = gateway.interp2app(W_DictMultiObject.descr_gt),
-    __ge__ = gateway.interp2app(W_DictMultiObject.descr_ge),
+    __eq__ = interp2app(W_DictMultiObject.descr_eq),
+    __ne__ = interp2app(W_DictMultiObject.descr_ne),
+    __lt__ = interp2app(W_DictMultiObject.descr_lt),
+    __le__ = interp2app(W_DictMultiObject.descr_le),
+    __gt__ = interp2app(W_DictMultiObject.descr_gt),
+    __ge__ = interp2app(W_DictMultiObject.descr_ge),
 
-    __len__ = gateway.interp2app(W_DictMultiObject.descr_len),
-    __iter__ = gateway.interp2app(W_DictMultiObject.descr_iter),
-    __contains__ = gateway.interp2app(W_DictMultiObject.descr_contains),
+    __len__ = interp2app(W_DictMultiObject.descr_len),
+    __iter__ = interp2app(W_DictMultiObject.descr_iter),
+    __contains__ = interp2app(W_DictMultiObject.descr_contains),
 
-    __getitem__ = gateway.interp2app(W_DictMultiObject.descr_getitem),
-    __setitem__ = gateway.interp2app(W_DictMultiObject.descr_setitem),
-    __delitem__ = gateway.interp2app(W_DictMultiObject.descr_delitem),
+    __getitem__ = interp2app(W_DictMultiObject.descr_getitem),
+    __setitem__ = interp2app(W_DictMultiObject.descr_setitem),
+    __delitem__ = interp2app(W_DictMultiObject.descr_delitem),
 
-    __reversed__ = gateway.interp2app(W_DictMultiObject.descr_reversed),
-    copy = gateway.interp2app(W_DictMultiObject.descr_copy),
-    items = gateway.interp2app(W_DictMultiObject.descr_items),
-    keys = gateway.interp2app(W_DictMultiObject.descr_keys),
-    values = gateway.interp2app(W_DictMultiObject.descr_values),
-    iteritems = gateway.interp2app(W_DictMultiObject.descr_iteritems),
-    iterkeys = gateway.interp2app(W_DictMultiObject.descr_iterkeys),
-    itervalues = gateway.interp2app(W_DictMultiObject.descr_itervalues),
-    viewkeys = gateway.interp2app(W_DictMultiObject.descr_viewkeys),
-    viewitems = gateway.interp2app(W_DictMultiObject.descr_viewitems),
-    viewvalues = gateway.interp2app(W_DictMultiObject.descr_viewvalues),
-    has_key = gateway.interp2app(W_DictMultiObject.descr_has_key),
-    clear = gateway.interp2app(W_DictMultiObject.descr_clear),
-    get = gateway.interp2app(W_DictMultiObject.descr_get),
-    pop = gateway.interp2app(W_DictMultiObject.descr_pop),
-    popitem = gateway.interp2app(W_DictMultiObject.descr_popitem),
-    setdefault = gateway.interp2app(W_DictMultiObject.descr_setdefault),
-    update = gateway.interp2app(W_DictMultiObject.descr_update),
+    __reversed__ = interp2app(W_DictMultiObject.descr_reversed),
+    copy = interp2app(W_DictMultiObject.descr_copy),
+    items = interp2app(W_DictMultiObject.descr_items),
+    keys = interp2app(W_DictMultiObject.descr_keys),
+    values = interp2app(W_DictMultiObject.descr_values),
+    iteritems = interp2app(W_DictMultiObject.descr_iteritems),
+    iterkeys = interp2app(W_DictMultiObject.descr_iterkeys),
+    itervalues = interp2app(W_DictMultiObject.descr_itervalues),
+    viewkeys = interp2app(W_DictMultiObject.descr_viewkeys),
+    viewitems = interp2app(W_DictMultiObject.descr_viewitems),
+    viewvalues = interp2app(W_DictMultiObject.descr_viewvalues),
+    has_key = interp2app(W_DictMultiObject.descr_has_key),
+    clear = interp2app(W_DictMultiObject.descr_clear),
+    get = interp2app(W_DictMultiObject.descr_get),
+    pop = interp2app(W_DictMultiObject.descr_pop),
+    popitem = interp2app(W_DictMultiObject.descr_popitem),
+    setdefault = interp2app(W_DictMultiObject.descr_setdefault),
+    update = interp2app(W_DictMultiObject.descr_update),
     )
 
 
@@ -441,7 +436,7 @@
     def w_keys(self, w_dict):
         iterator = self.iterkeys(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_key = iterator.next_key()
             if w_key is not None:
                 result.append(w_key)
@@ -451,7 +446,7 @@
     def values(self, w_dict):
         iterator = self.itervalues(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_value = iterator.next_value()
             if w_value is not None:
                 result.append(w_value)
@@ -461,7 +456,7 @@
     def items(self, w_dict):
         iterator = self.iteritems(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_key, w_value = iterator.next_item()
             if w_key is not None:
                 result.append(self.space.newtuple([w_key, w_value]))
@@ -503,7 +498,7 @@
     unerase = staticmethod(unerase)
 
     def get_empty_storage(self):
-       return self.erase(None)
+        return self.erase(None)
 
     def switch_to_correct_strategy(self, w_dict, w_key):
         withidentitydict = self.space.config.objspace.std.withidentitydict
@@ -606,7 +601,7 @@
 # Iterator Implementation base classes
 
 def _new_next(TP):
-    if TP == 'key' or TP == 'value':
+    if TP in ('key', 'value'):
         EMPTY = None
     else:
         EMPTY = None, None
@@ -614,10 +609,12 @@
     def next(self):
         if self.dictimplementation is None:
             return EMPTY
+        space = self.space
         if self.len != self.dictimplementation.length():
             self.len = -1   # Make this error state sticky
-            raise OperationError(self.space.w_RuntimeError,
-                     self.space.wrap("dictionary changed size during iteration"))
+            msg = "dictionary changed size during iteration"
+            raise OperationError(space.w_RuntimeError, space.wrap(msg))
+
         # look for the next entry
         if self.pos < self.len:
             result = getattr(self, 'next_' + TP + '_entry')()
@@ -635,8 +632,8 @@
                 w_value = self.dictimplementation.getitem(w_key)
                 if w_value is None:
                     self.len = -1   # Make this error state sticky
-                    raise OperationError(self.space.w_RuntimeError,
-                        self.space.wrap("dictionary changed during iteration"))
+                    msg = "dictionary changed during iteration"
+                    raise OperationError(space.w_RuntimeError, space.wrap(msg))
                 return (w_key, w_value)
         # no more entries
         self.dictimplementation = None
@@ -769,7 +766,8 @@
 
     def setdefault(self, w_dict, w_key, w_default):
         if self.is_correct_type(w_key):
-            return self.unerase(w_dict.dstorage).setdefault(self.unwrap(w_key), w_default)
+            return self.unerase(w_dict.dstorage).setdefault(self.unwrap(w_key),
+                                                            w_default)
         else:
             self.switch_to_object_strategy(w_dict)
             return w_dict.setdefault(w_key, w_default)
@@ -809,7 +807,7 @@
         space = self.space
         dict_w = self.unerase(w_dict.dstorage)
         return [space.newtuple([self.wrap(key), w_value])
-                    for (key, w_value) in dict_w.iteritems()]
+                for (key, w_value) in dict_w.iteritems()]
 
     def popitem(self, w_dict):
         key, value = self.unerase(w_dict.dstorage).popitem()
@@ -854,9 +852,9 @@
         return True
 
     def get_empty_storage(self):
-       new_dict = r_dict(self.space.eq_w, self.space.hash_w,
-                         force_non_null=True)
-       return self.erase(new_dict)
+        new_dict = r_dict(self.space.eq_w, self.space.hash_w,
+                          force_non_null=True)
+        return self.erase(new_dict)
 
     def _never_equal_to(self, w_lookup_type):
         return False
@@ -1056,7 +1054,7 @@
                      w_dict_unrolling_heuristic(w_data))
 def update1_dict_dict(space, w_dict, w_data):
     iterator = w_data.iteritems()
-    while 1:
+    while True:
         w_key, w_value = iterator.next_item()
         if w_key is None:
             break
@@ -1094,16 +1092,18 @@
         update1(space, w_dict, w_kwds)
 
 def characterize(space, w_a, w_b):
-    """ (similar to CPython)
-    returns the smallest key in acontent for which b's value is different or absent and this value """
+    """(similar to CPython)
+    returns the smallest key in acontent for which b's value is
+    different or absent and this value"""
     w_smallest_diff_a_key = None
     w_its_value = None
     iteratorimplementation = w_a.iteritems()
-    while 1:
+    while True:
         w_key, w_val = iteratorimplementation.next_item()
         if w_key is None:
             break
-        if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
+        if w_smallest_diff_a_key is None or space.is_true(space.lt(
+                w_key, w_smallest_diff_a_key)):
             w_bvalue = w_b.getitem(w_key)
             if w_bvalue is None:
                 w_its_value = w_val
@@ -1151,7 +1151,7 @@
         w_mod    = space.getbuiltinmodule('_pickle_support')
         mod      = space.interp_w(MixedModule, w_mod)
         new_inst = mod.get('dictiter_surrogate_new')
-        w_typeobj = space.gettypeobject(W_BaseDictMultiIterObject.typedef)
+        w_typeobj = space.type(self)
 
         raise OperationError(
             space.w_TypeError,
@@ -1159,12 +1159,15 @@
         # XXXXXX get that working again
 
         # we cannot call __init__ since we don't have the original dict
-        if isinstance(self, W_DictIter_Keys):
-            w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj)
-        elif isinstance(self, W_DictIter_Values):
-            w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj)
-        elif isinstance(self, W_DictIter_Items):
-            w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj)
+        if isinstance(self, W_DictMultiIterKeysObject):
+            w_clone = space.allocate_instance(W_DictMultiIterKeysObject,
+                                              w_typeobj)
+        elif isinstance(self, W_DictMultiIterValuesObject):
+            w_clone = space.allocate_instance(W_DictMultiIterValuesObject,
+                                              w_typeobj)
+        elif isinstance(self, W_DictMultiIterItemsObject):
+            w_clone = space.allocate_instance(W_DictMultiIterItemsObject,
+                                              w_typeobj)
         else:
             msg = "unsupported dictiter type '%s' during pickling" % (self,)
             raise OperationError(space.w_TypeError, space.wrap(msg))
@@ -1179,10 +1182,7 @@
             w_clone.pos += 1
         stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)]
         w_res = space.newlist(stuff)
-        tup      = [
-            w_res
-        ]
-        w_ret = space.newtuple([new_inst, space.newtuple(tup)])
+        w_ret = space.newtuple([new_inst, space.newtuple([w_res])])
         return w_ret
 
 
@@ -1212,23 +1212,26 @@
 
 W_DictMultiIterItemsObject.typedef = StdTypeDef(
     "dict_iteritems",
-    __iter__ = gateway.interp2app(W_DictMultiIterItemsObject.descr_iter),
-    next = gateway.interp2app(W_DictMultiIterItemsObject.descr_next),
-    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    __iter__ = interp2app(W_DictMultiIterItemsObject.descr_iter),
+    next = interp2app(W_DictMultiIterItemsObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
     )
 
 W_DictMultiIterKeysObject.typedef = StdTypeDef(
     "dict_iterkeys",
-    __iter__ = gateway.interp2app(W_DictMultiIterKeysObject.descr_iter),
-    next = gateway.interp2app(W_DictMultiIterKeysObject.descr_next),
-    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    __iter__ = interp2app(W_DictMultiIterKeysObject.descr_iter),
+    next = interp2app(W_DictMultiIterKeysObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
     )
 
 W_DictMultiIterValuesObject.typedef = StdTypeDef(
     "dict_itervalues",
-    __iter__ = gateway.interp2app(W_DictMultiIterValuesObject.descr_iter),
-    next = gateway.interp2app(W_DictMultiIterValuesObject.descr_next),
-    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    __iter__ = interp2app(W_DictMultiIterValuesObject.descr_iter),
+    next = interp2app(W_DictMultiIterValuesObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
     )
 
 
@@ -1245,45 +1248,88 @@
         return space.wrap("%s(%s)" % (space.type(self).getname(space),
                                       space.str_w(w_repr)))
 
-    def descr_eq(self, space, w_otherview):
-        if not space.eq_w(space.len(self), space.len(w_otherview)):
-            return space.w_False
-
-        w_iter = space.iter(self)
-        while True:
-            try:
-                w_item = space.next(w_iter)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
-                break
-            if not space.is_true(space.contains(w_otherview, w_item)):
-                return space.w_False
-        return space.w_True
-
     def descr_len(self, space):
         return space.len(self.w_dict)
 
-    def descr_and(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "intersection_update", w_otherview)
-        return w_set
+def _all_contained_in(space, w_dictview, w_other):
+    w_iter = space.iter(w_dictview)
+    for w_item in space.iteriterable(w_iter):
+        if not space.is_true(space.contains(w_other, w_item)):
+            return space.w_False
+    return space.w_True
 
-    def descr_or(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "update", w_otherview)
-        return w_set
+def _is_set_like(w_other):
+    from pypy.objspace.std.setobject import W_BaseSetObject
+    return (isinstance(w_other, W_BaseSetObject) or
+            isinstance(w_other, W_DictViewKeysObject) or
+            isinstance(w_other, W_DictViewItemsObject))
 
-    def descr_xor(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "symmetric_difference_update", w_otherview)
-        return w_set
+class SetLikeDictView(object):
+    _mixin_ = True
 
-class W_DictViewItemsObject(W_DictViewObject):
+    def descr_eq(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) == space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_ne(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        return space.not_(space.eq(self, w_other))
+
+    def descr_lt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) < space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_le(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) <= space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_gt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) > space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def descr_ge(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) >= space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def _as_set_op(name, methname):
+        @func_renamer('descr_' + name)
+        def op(self, space, w_other):
+            w_set = space.call_function(space.w_set, self)
+            space.call_method(w_set, methname, w_other)
+            return w_set
+        @func_renamer('descr_r' + name)
+        def rop(self, space, w_other):
+            w_set = space.call_function(space.w_set, w_other)
+            space.call_method(w_set, methname, self)
+            return w_set
+        return op, rop
+
+    descr_sub, descr_rsub = _as_set_op('sub', 'difference_update')
+    descr_and, descr_rand = _as_set_op('and', 'intersection_update')
+    descr_or, descr_ror = _as_set_op('or', 'update')
+    descr_xor, descr_rxor = _as_set_op('xor', 'symmetric_difference_update')
+
+class W_DictViewItemsObject(W_DictViewObject, SetLikeDictView):
     def descr_iter(self, space):
         return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
 
-class W_DictViewKeysObject(W_DictViewObject):
+class W_DictViewKeysObject(W_DictViewObject, SetLikeDictView):
     def descr_iter(self, space):
         return W_DictMultiIterKeysObject(space, self.w_dict.iterkeys())
 
@@ -1293,33 +1339,53 @@
 
 W_DictViewItemsObject.typedef = StdTypeDef(
     "dict_items",
-    __repr__ = gateway.interp2app(W_DictViewItemsObject.descr_repr),
-    __eq__ = gateway.interp2app(W_DictViewItemsObject.descr_eq),
-    __len__ = gateway.interp2app(W_DictViewItemsObject.descr_len),
-    __iter__ = gateway.interp2app(W_DictViewItemsObject.descr_iter),
-    __and__ = gateway.interp2app(W_DictViewItemsObject.descr_and),
-    __or__ = gateway.interp2app(W_DictViewItemsObject.descr_or),
-    __xor__ = gateway.interp2app(W_DictViewItemsObject.descr_xor)
+    __repr__ = interp2app(W_DictViewItemsObject.descr_repr),
+    __len__ = interp2app(W_DictViewItemsObject.descr_len),
+    __iter__ = interp2app(W_DictViewItemsObject.descr_iter),
+
+    __eq__ = interp2app(W_DictViewItemsObject.descr_eq),
+    __ne__ = interp2app(W_DictViewItemsObject.descr_ne),
+    __lt__ = interp2app(W_DictViewItemsObject.descr_lt),
+    __le__ = interp2app(W_DictViewItemsObject.descr_le),
+    __gt__ = interp2app(W_DictViewItemsObject.descr_gt),
+    __ge__ = interp2app(W_DictViewItemsObject.descr_ge),
+
+    __sub__ = interp2app(W_DictViewItemsObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewItemsObject.descr_rsub),
+    __and__ = interp2app(W_DictViewItemsObject.descr_and),
+    __rand__ = interp2app(W_DictViewItemsObject.descr_rand),
+    __or__ = interp2app(W_DictViewItemsObject.descr_or),
+    __ror__ = interp2app(W_DictViewItemsObject.descr_ror),
+    __xor__ = interp2app(W_DictViewItemsObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewItemsObject.descr_rxor),
     )
 
 W_DictViewKeysObject.typedef = StdTypeDef(
     "dict_keys",
-    __repr__ = gateway.interp2app(W_DictViewKeysObject.descr_repr),
-    __eq__ = gateway.interp2app(W_DictViewKeysObject.descr_eq),
-    __len__ = gateway.interp2app(W_DictViewKeysObject.descr_len),
-    __iter__ = gateway.interp2app(W_DictViewKeysObject.descr_iter),
-    __and__ = gateway.interp2app(W_DictViewKeysObject.descr_and),
-    __or__ = gateway.interp2app(W_DictViewKeysObject.descr_or),
-    __xor__ = gateway.interp2app(W_DictViewKeysObject.descr_xor)
+    __repr__ = interp2app(W_DictViewKeysObject.descr_repr),
+    __len__ = interp2app(W_DictViewKeysObject.descr_len),
+    __iter__ = interp2app(W_DictViewKeysObject.descr_iter),
+
+    __eq__ = interp2app(W_DictViewKeysObject.descr_eq),
+    __ne__ = interp2app(W_DictViewKeysObject.descr_ne),
+    __lt__ = interp2app(W_DictViewKeysObject.descr_lt),
+    __le__ = interp2app(W_DictViewKeysObject.descr_le),
+    __gt__ = interp2app(W_DictViewKeysObject.descr_gt),
+    __ge__ = interp2app(W_DictViewKeysObject.descr_ge),
+
+    __sub__ = interp2app(W_DictViewKeysObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewKeysObject.descr_rsub),
+    __and__ = interp2app(W_DictViewKeysObject.descr_and),
+    __rand__ = interp2app(W_DictViewKeysObject.descr_rand),
+    __or__ = interp2app(W_DictViewKeysObject.descr_or),
+    __ror__ = interp2app(W_DictViewKeysObject.descr_ror),
+    __xor__ = interp2app(W_DictViewKeysObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewKeysObject.descr_rxor),
     )
 
 W_DictViewValuesObject.typedef = StdTypeDef(
     "dict_values",
-    __repr__ = gateway.interp2app(W_DictViewValuesObject.descr_repr),
-    __eq__ = gateway.interp2app(W_DictViewValuesObject.descr_eq),
-    __len__ = gateway.interp2app(W_DictViewValuesObject.descr_len),
-    __iter__ = gateway.interp2app(W_DictViewValuesObject.descr_iter),
-    __and__ = gateway.interp2app(W_DictViewValuesObject.descr_and),
-    __or__ = gateway.interp2app(W_DictViewValuesObject.descr_or),
-    __xor__ = gateway.interp2app(W_DictViewValuesObject.descr_xor)
+    __repr__ = interp2app(W_DictViewValuesObject.descr_repr),
+    __len__ = interp2app(W_DictViewValuesObject.descr_len),
+    __iter__ = interp2app(W_DictViewValuesObject.descr_iter),
     )
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -696,6 +696,7 @@
         assert d.viewkeys() == e.viewkeys()
         del e["a"]
         assert d.viewkeys() != e.viewkeys()
+        assert not d.viewkeys() == 42
 
     def test_dict_items(self):
         d = {1: 10, "a": "ABC"}
@@ -720,6 +721,7 @@
         assert d.viewitems() == e.viewitems()
         e["a"] = "def"
         assert d.viewitems() != e.viewitems()
+        assert not d.viewitems() == 42
 
     def test_dict_mixed_keys_items(self):
         d = {(1, 1): 11, (2, 2): 22}
@@ -732,6 +734,7 @@
         values = d.viewvalues()
         assert set(values) == set([10, "ABC"])
         assert len(values) == 2
+        assert not values == 42
 
     def test_dict_repr(self):
         d = {1: 10, "a": "ABC"}
@@ -774,6 +777,13 @@
         assert d1.viewkeys() ^ set(d2.viewkeys()) == set('ac')
         assert d1.viewkeys() ^ set(d3.viewkeys()) == set('abde')
 
+        assert d1.viewkeys() - d1.viewkeys() == set()
+        assert d1.viewkeys() - d2.viewkeys() == set('a')
+        assert d1.viewkeys() - d3.viewkeys() == set('ab')
+        assert d1.viewkeys() - set(d1.viewkeys()) == set()
+        assert d1.viewkeys() - set(d2.viewkeys()) == set('a')
+        assert d1.viewkeys() - set(d3.viewkeys()) == set('ab')
+
     def test_items_set_operations(self):
         d1 = {'a': 1, 'b': 2}
         d2 = {'a': 2, 'b': 2}
@@ -802,6 +812,113 @@
         assert (d1.viewitems() ^ d3.viewitems() ==
                 set([('a', 1), ('b', 2), ('d', 4), ('e', 5)]))
 
+        assert d1.viewitems() - d1.viewitems() == set()
+        assert d1.viewitems() - d2.viewitems() == set([('a', 1)])
+        assert d1.viewitems() - d3.viewitems() == set([('a', 1), ('b', 2)])
+
+    def test_keys_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewkeys() & set([1]) == set([1])
+        assert d.viewkeys() & {1: u'foo'} == set([1])
+        assert d.viewkeys() & [1, 2] == set([1, 2])
+        #
+        assert set([1]) & d.viewkeys() == set([1])
+        assert {1: u'foo'} & d.viewkeys() == set([1])
+        assert [1, 2] & d.viewkeys() == set([1, 2])
+        #
+        assert d.viewkeys() - set([1]) == set([2, 3])
+        assert set([1, 4]) - d.viewkeys() == set([4])
+        #
+        assert d.viewkeys() == set([1, 2, 3])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([1, 2, 3]) == d.viewkeys()
+        assert d.viewkeys() == frozenset(set([1, 2, 3]))
+        #assert frozenset(set([1, 2, 3])) == d.viewkeys()
+        assert not d.viewkeys() != set([1, 2, 3])
+        #assert not set([1, 2, 3]) != d.viewkeys()
+        assert not d.viewkeys() != frozenset(set([1, 2, 3]))
+        #assert not frozenset(set([1, 2, 3])) != d.viewkeys()
+
+    def test_items_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewitems() & set([(1, u'a')]) == set([(1, u'a')])
+        assert d.viewitems() & {(1, u'a'): u'foo'} == set([(1, u'a')])
+        assert d.viewitems() & [(1, u'a'), (2, u'b')] == set([(1, u'a'), (2, u'b')])
+        #
+        assert set([(1, u'a')]) & d.viewitems() == set([(1, u'a')])
+        assert {(1, u'a'): u'foo'} & d.viewitems() == set([(1, u'a')])
+        assert [(1, u'a'), (2, u'b')] & d.viewitems() == set([(1, u'a'), (2, u'b')])
+        #
+        assert d.viewitems() - set([(1, u'a')]) == set([(2, u'b'), (3, u'c')])
+        assert set([(1, u'a'), 4]) - d.viewitems() == set([4])
+        #
+        assert d.viewitems() == set([(1, u'a'), (2, u'b'), (3, u'c')])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([(1, u'a'), (2, u'b'), (3, u'c')]) == d.viewitems()
+        assert d.viewitems() == frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')]))
+        #assert frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) == d.viewitems()
+        assert not d.viewitems() != set([(1, u'a'), (2, u'b'), (3, u'c')])
+        #assert not set([(1, u'a'), (2, u'b'), (3, u'c')]) != d.viewitems()
+        assert not d.viewitems() != frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')]))
+        #assert not frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) != d.viewitems()
+
+    def test_dictviewset_unhashable_values(self):
+        class C:
+            def __eq__(self, other):
+                return True
+        d = {1: C()}
+        assert d.viewitems() <= d.viewitems()
+
+    def test_compare_keys_and_items(self):
+        d1 = {1: 2}
+        d2 = {(1, 2): 'foo'}
+        assert d1.viewitems() == d2.viewkeys()
+
+    def test_keys_items_contained(self):
+        def helper(fn):
+            empty = fn(dict())
+            empty2 = fn(dict())
+            smaller = fn({1:1, 2:2})
+            larger = fn({1:1, 2:2, 3:3})
+            larger2 = fn({1:1, 2:2, 3:3})
+            larger3 = fn({4:1, 2:2, 3:3})
+
+            assert smaller <  larger
+            assert smaller <= larger
+            assert larger >  smaller
+            assert larger >= smaller
+
+            assert not smaller >= larger
+            assert not smaller >  larger
+            assert not larger  <= smaller
+            assert not larger  <  smaller
+
+            assert not smaller <  larger3
+            assert not smaller <= larger3
+            assert not larger3 >  smaller
+            assert not larger3 >= smaller
+
+            # Inequality strictness
+            assert larger2 >= larger
+            assert larger2 <= larger
+            assert not larger2 > larger
+            assert not larger2 < larger
+
+            assert larger == larger2
+            assert smaller != larger
+
+            # There is an optimization on the zero-element case.
+            assert empty == empty2
+            assert not empty != empty2
+            assert not empty == smaller
+            assert empty != smaller
+
+            # With the same size, an elementwise compare happens
+            assert larger != larger3
+            assert not larger == larger3
+
+        helper(lambda x: x.viewkeys())
+        helper(lambda x: x.viewitems())
 
 class AppTestStrategies(object):
     def setup_class(cls):
diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py
--- a/rpython/memory/gc/env.py
+++ b/rpython/memory/gc/env.py
@@ -1,9 +1,10 @@
 """
 Utilities to get environ variables and platform-specific memory-related values.
 """
-import os, sys
+import os, sys, platform
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
+from rpython.rlib.rstring import assert_str0
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.lltypesystem.lloperation import llop
 
@@ -130,7 +131,22 @@
 
 # ---------- Linux2 ----------
 
-def get_L2cache_linux2(filename="/proc/cpuinfo"):
+def get_L2cache_linux2():
+    arch = platform.machine()
+    if arch.endswith('86') or arch == 'x86_64':
+        return get_L2cache_linux2_cpuinfo()
+    if arch in ('alpha', 'ppc', 'ppc64'):
+        return get_L2cache_linux2_cpuinfo(label='L2 cache')
+    if arch == 'ia64':
+        return get_L2cache_linux2_ia64()
+    if arch in ('parisc', 'parisc64'):
+        return get_L2cache_linux2_cpuinfo(label='D-cache')
+    if arch in ('sparc', 'sparc64'):
+        return get_L2cache_linux2_sparc()
+    return -1
+
+
+def get_L2cache_linux2_cpuinfo(filename="/proc/cpuinfo", label='cache size'):
     debug_start("gc-hardware")
     L2cache = sys.maxint
     try:
@@ -149,12 +165,8 @@
     else:
         data = ''.join(data)
         linepos = 0
-        # Currently on ARM-linux we won't find any information about caches in
-        # cpuinfo
-        if _detect_arm_cpu(data):
-            return -1
         while True:
-            start = _findend(data, '\ncache size', linepos)
+            start = _findend(data, '\n' + label, linepos)
             if start < 0:
                 break    # done
             linepos = _findend(data, '\n', start)
@@ -194,6 +206,104 @@
             "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
         return -1
 
+def get_L2cache_linux2_sparc():
+    debug_start("gc-hardware")
+    cpu = 0
+    L2cache = sys.maxint
+    while True:
+        try:
+            fd = os.open('/sys/devices/system/cpu/cpu' + assert_str0(str(cpu))
+                         + '/l2_cache_size', os.O_RDONLY, 0644)
+            try:
+                number = int(os.read(fd, 4096))
+            finally:
+                os.close(fd)
+        except OSError:
+            break
+        if number < L2cache:
+            L2cache = number
+        cpu += 1
+
+    debug_print("L2cache =", L2cache)
+    debug_stop("gc-hardware")
+    if L2cache < sys.maxint:
+        return L2cache
+    else:
+        # Print a top-level warning even in non-debug builds
+        llop.debug_print(lltype.Void,
+            "Warning: cannot find your CPU L2 cache size in "
+            "/sys/devices/system/cpu/cpuX/l2_cache_size")
+        return -1
+
+def get_L2cache_linux2_ia64():
+    debug_start("gc-hardware")
+    cpu = 0
+    L2cache = sys.maxint
+    L3cache = sys.maxint
+    while True:
+        cpudir = '/sys/devices/system/cpu/cpu' + assert_str0(str(cpu))
+        index = 0
+        while True:
+            cachedir = cpudir + '/cache/index' + assert_str0(str(index))
+            try:
+                fd = os.open(cachedir + '/level', os.O_RDONLY, 0644)
+                try:
+                    level = int(os.read(fd, 4096)[:-1])
+                finally:
+                    os.close(fd)
+            except OSError:
+                break
+            if level not in (2, 3):
+                index += 1
+                continue
+            try:
+                fd = os.open(cachedir + '/size', os.O_RDONLY, 0644)
+                try:
+                    data = os.read(fd, 4096)
+                finally:
+                    os.close(fd)
+            except OSError:
+                break
+
+            end = 0
+            while '0' <= data[end] <= '9':
+                end += 1
+            if end == 0:
+                index += 1
+                continue
+            if data[end] not in ('K', 'k'):    # assume kilobytes for now
+                index += 1
+                continue
+
+            number = int(data[:end])
+            number *= 1024
+
+            if level == 2:
+                if number < L2cache:
+                    L2cache = number
+            if level == 3:
+                if number < L3cache:
+                    L3cache = number
+
+            index += 1
+
+        if index == 0:
+            break
+        cpu += 1
+
+    mangled = L2cache + L3cache
+    debug_print("L2cache =", mangled)
+    debug_stop("gc-hardware")
+    if mangled > 0:
+        return mangled
+    else:
+        # Print a top-level warning even in non-debug builds
+        llop.debug_print(lltype.Void,
+            "Warning: cannot find your CPU L2 & L3 cache size in "
+            "/sys/devices/system/cpu/cpuX/cache")
+        return -1
+
+
 def _findend(data, pattern, pos):
     pos = data.find(pattern, pos)
     if pos < 0:
@@ -205,11 +315,6 @@
         pos += 1
     return pos
 
-def _detect_arm_cpu(data):
-    # check for the presence of a 'Processor' entry
-    p = _findend(data, 'Processor', 0)
-    return p >= 0 and _findend(data, 'ARMv', p) > 0
-
 # ---------- Darwin ----------
 
 sysctlbyname = rffi.llexternal('sysctlbyname',
diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py
--- a/rpython/memory/gc/test/test_env.py
+++ b/rpython/memory/gc/test/test_env.py
@@ -159,25 +159,5 @@
 fpu     : yes
 etc.
 """)
-    result = env.get_L2cache_linux2(str(filepath))
+    result = env.get_L2cache_linux2_cpuinfo(str(filepath))
     assert result == 3072 * 1024
-
-def test_estimate_best_nursery_size_linux2_arm():
-    filepath = udir.join('estimate_best_nursery_size_linux2')
-    filepath.write("""\
-Processor       : ARMv6-compatible processor rev 7 (v6l)
-# this is not actually from cpuinfo, but here for the test
-cache size      : 3072 KB
-...
-""")
-    result = env.get_L2cache_linux2(str(filepath))
-    assert result == -1
-
-def test__detect_arm():
-    assert env._detect_arm_cpu("Processor       : ARMv6-compatible processor rev 7 (v6l)")
-    assert not env._detect_arm_cpu("""\
-processor   : 0
-vendor_id   : GenuineIntel
-cpu family  : 6
-model       : 37
-""")
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -447,11 +447,11 @@
 
     @jit.elidable
     def repr(self):
-        return _format(self, BASE10, '', 'L')
+        return _format_decimal(self, addL=True)
 
     @jit.elidable
     def str(self):
-        return _format(self, BASE10)
+        return _format_decimal(self)
 
     @jit.elidable
     def eq(self, other):
@@ -2101,6 +2101,101 @@
     return ''.join(s[p:])
 
 
+DECIMAL_SHIFT = 0      # computed as max(E such that 10**E fits in a digit)
+while 10 ** (DECIMAL_SHIFT + 1) <= 2 ** SHIFT:
+    DECIMAL_SHIFT += 1
+DECIMAL_BASE = 10 ** DECIMAL_SHIFT
+
+# an RPython trick: this creates a nested sequence of calls that are
+# all inlined into each other, making an unrolled loop.  Moreover the
+# calls are done in the "wrong" order to be written as a regular loop:
+# the first digit that is append-ed to the builder is the most
+# significant one (corresponding to the innermost call).
+_succ = specialize.memo()(lambda n: n + 1)
+ at specialize.arg(3)
+def _add_decimal_digits(builder, value, ndigits, digit_index=1):
+    assert value >= 0
+    if digit_index < ndigits:
+        assert digit_index < DECIMAL_SHIFT
+        _add_decimal_digits(builder, value // 10, ndigits, _succ(digit_index))
+        builder.append(chr(ord('0') + value % 10))
+    else:
+        assert value < 10
+        builder.append(chr(ord('0') + value))
+_add_decimal_digits._always_inline_ = True
+
+
+def _format_decimal(a, addL=False):
+    """ Optimized version of _format(a, BASE10, '', 'L' if addL else ''). """
+    if a.sign == 0:
+        if addL:
+            return "0L"
+        else:
+            return "0"
+
+    size_a = a.numdigits()
+    negative = a.sign < 0
+
+    # quick and dirty upper bound for the number of digits
+    # required to express a in base DECIMAL_BASE:
+    #
+    #    #digits = 1 + floor(log2(a) / log2(DECIMAL_BASE))
+    #
+    # But log2(a) < size_a * PyLong_SHIFT, and
+    # log2(DECIMAL_BASE) = log2(10) * DECIMAL_SHIFT
+    #                    > 3 * DECIMAL_SHIFT
+
+    size = 1 + size_a * SHIFT // (3 * DECIMAL_SHIFT)
+    pout = [NULLDIGIT] * size
+
+    # convert array of base _PyLong_BASE digits in pin to an array of
+    # base _PyLong_DECIMAL_BASE digits in pout, following Knuth (TAOCP,
+    # Volume 2 (3rd edn), section 4.4, Method 1b).
+    size = 0
+    for i in range(size_a-1, -1, -1):
+        hi = a.digit(i)
+        for j in range(size):
+            z = (_widen_digit(pout[j]) << SHIFT) | hi
+            hi = _store_digit(z // DECIMAL_BASE)
+            pout[j] = _store_digit(z - _widen_digit(hi) * DECIMAL_BASE)
+        assert hi >= 0
+        while hi:
+            pout[size] = hi % DECIMAL_BASE
+            hi //= DECIMAL_BASE
+            size += 1
+    sizem1 = size - 1
+    assert sizem1 >= 0
+
+    # calculate exact length of output string, and allocate
+    decimal_digits_in_last_part = 1
+    rem = pout[sizem1]
+    tenpow = 10
+    while rem >= tenpow:
+        tenpow *= 10
+        decimal_digits_in_last_part += 1
+    strlen = (addL + negative +
+              decimal_digits_in_last_part + (sizem1) * DECIMAL_SHIFT)
+
+    builder = StringBuilder(strlen)
+
+    # start with the negative sign, if needed
+    if negative:
+        builder.append('-')
+
+    # pout[size-1] produces 'decimal_digits_in_last_part' digits.
+    # Then the remaining pout[size-2] through pout[0] contribute exactly
+    # DECIMAL_SHIFT digits each.
+    decimal_digits = decimal_digits_in_last_part
+    for i in range(sizem1, -1, -1):
+        _add_decimal_digits(builder, pout[i], decimal_digits)
+        decimal_digits = DECIMAL_SHIFT
+
+    # done
+    if addL:
+        builder.append('L')
+    return builder.build()
+
+
 def _bitwise(a, op, b): # '&', '|', '^'
     """ Bitwise and/or/xor operations """
 
diff --git a/rpython/translator/c/src/stacklet/tests.c b/rpython/translator/c/src/stacklet/tests.c
--- a/rpython/translator/c/src/stacklet/tests.c
+++ b/rpython/translator/c/src/stacklet/tests.c
@@ -31,7 +31,7 @@
   assert(status == 0);
   status = 1;
   assert(h != EMPTY_STACKLET_HANDLE);
-  h = stacklet_switch(thrd, h);
+  h = stacklet_switch(h);
   assert(status == 2);
   assert(h != EMPTY_STACKLET_HANDLE);
   status = 3;
@@ -45,7 +45,7 @@
   assert(h != EMPTY_STACKLET_HANDLE);
   assert(status == 1);
   status = 2;
-  h = stacklet_switch(thrd, h);
+  h = stacklet_switch(h);
   assert(status == 3);
   assert(h == EMPTY_STACKLET_HANDLE);
 }
@@ -148,7 +148,7 @@
           //printf("switch to %d\n", n);
           h = handles[n];
           handles[n] = NULL;
-          h = stacklet_switch(thrd, h);
+          h = stacklet_switch(h);
         }
       //printf("back in self = %d, coming from %d\n", self, comefrom);
       assert(nextstep == status);
diff --git a/rpython/translator/platform/freebsd.py b/rpython/translator/platform/freebsd.py
--- a/rpython/translator/platform/freebsd.py
+++ b/rpython/translator/platform/freebsd.py
@@ -12,3 +12,11 @@
 
 class Freebsd_64(Freebsd):
     shared_only = ('-fPIC',)
+
+class GNUkFreebsd(Freebsd):
+    DEFAULT_CC = 'cc'
+    extra_libs = ('-lrt',)
+
+class GNUkFreebsd_64(Freebsd_64):
+    DEFAULT_CC = 'cc'
+    extra_libs = ('-lrt',)


More information about the pypy-commit mailing list