[pypy-commit] pypy win64-stage1: Merge with default

ctismer noreply at buildbot.pypy.org
Tue Mar 27 05:09:09 CEST 2012


Author: Christian Tismer <tismer at stackless.com>
Branch: win64-stage1
Changeset: r54021:ceb003ff6d6f
Date: 2012-03-27 03:33 +0100
http://bitbucket.org/pypy/pypy/changeset/ceb003ff6d6f/

Log:	Merge with default

diff --git a/lib-python/modified-2.7/test/test_set.py b/lib-python/modified-2.7/test/test_set.py
--- a/lib-python/modified-2.7/test/test_set.py
+++ b/lib-python/modified-2.7/test/test_set.py
@@ -1568,7 +1568,7 @@
             for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint):
                 for g in (G, I, Ig, L, R):
                     expected = meth(data)
-                    actual = meth(G(data))
+                    actual = meth(g(data))
                     if isinstance(expected, bool):
                         self.assertEqual(actual, expected)
                     else:
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -10,16 +10,6 @@
 from pypy.interpreter.astcompiler import ast, consts
 
 
-try:
-    all
-except NameError:
-    def all(iterable):
-        for x in iterable:
-            if not x:
-                return False
-        return True
-
-
 class TestAstBuilder:
 
     def setup_class(cls):
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -16,7 +16,7 @@
         a[i][i] = 1
     return a
 
-def sum(a,axis=None):
+def sum(a,axis=None, out=None):
     '''sum(a, axis=None)
     Sum of array elements over a given axis.
 
@@ -43,17 +43,17 @@
     # TODO: add to doc (once it's implemented): cumsum : Cumulative sum of array elements.
     if not hasattr(a, "sum"):
         a = _numpypy.array(a)
-    return a.sum(axis)
+    return a.sum(axis=axis, out=out)
 
-def min(a, axis=None):
+def min(a, axis=None, out=None):
     if not hasattr(a, "min"):
         a = _numpypy.array(a)
-    return a.min(axis)
+    return a.min(axis=axis, out=out)
 
-def max(a, axis=None):
+def max(a, axis=None, out=None):
     if not hasattr(a, "max"):
         a = _numpypy.array(a)
-    return a.max(axis)
+    return a.max(axis=axis, out=out)
 
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -62,21 +62,24 @@
         return space.wrap(dtype.itemtype.bool(self))
 
     def _binop_impl(ufunc_name):
-        def impl(self, space, w_other):
+        def impl(self, space, w_other, w_out=None):
             from pypy.module.micronumpy import interp_ufuncs
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space,
+                                                            [self, w_other, w_out])
         return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
 
     def _binop_right_impl(ufunc_name):
-        def impl(self, space, w_other):
+        def impl(self, space, w_other, w_out=None):
             from pypy.module.micronumpy import interp_ufuncs
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, 
+                                                            [w_other, self, w_out])
         return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
 
     def _unaryop_impl(ufunc_name):
-        def impl(self, space):
+        def impl(self, space, w_out=None):
             from pypy.module.micronumpy import interp_ufuncs
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space,
+                                                                    [self, w_out])
         return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
 
     descr_add = _binop_impl("add")
diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py
--- a/pypy/module/micronumpy/interp_iter.py
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -269,7 +269,7 @@
 
     def apply_transformations(self, arr, transformations):
         v = BaseIterator.apply_transformations(self, arr, transformations)
-        if len(arr.shape) == 1:
+        if len(arr.shape) == 1 and len(v.res_shape) == 1:
             return OneDimIterator(self.offset, self.strides[0],
                                   self.res_shape[0])
         return v
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -83,8 +83,9 @@
         return space.wrap(W_NDimArray(shape[:], dtype=dtype))
 
     def _unaryop_impl(ufunc_name):
-        def impl(self, space):
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+        def impl(self, space, w_out=None):
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space,
+                                                                [self, w_out])
         return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
 
     descr_pos = _unaryop_impl("positive")
@@ -93,8 +94,9 @@
     descr_invert = _unaryop_impl("invert")
 
     def _binop_impl(ufunc_name):
-        def impl(self, space, w_other):
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+        def impl(self, space, w_other, w_out=None):
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space,
+                                                        [self, w_other, w_out])
         return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
 
     descr_add = _binop_impl("add")
@@ -124,12 +126,12 @@
         return space.newtuple([w_quotient, w_remainder])
 
     def _binop_right_impl(ufunc_name):
-        def impl(self, space, w_other):
+        def impl(self, space, w_other, w_out=None):
             w_other = scalar_w(space,
                 interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()),
                 w_other
             )
-            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out])
         return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
 
     descr_radd = _binop_right_impl("add")
@@ -152,13 +154,21 @@
         return space.newtuple([w_quotient, w_remainder])
 
     def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
-        def impl(self, space, w_axis=None):
+        def impl(self, space, w_axis=None, w_out=None):
             if space.is_w(w_axis, space.w_None):
                 axis = -1
             else:
                 axis = space.int_w(w_axis)
+            if space.is_w(w_out, space.w_None) or not w_out:
+                out = None
+            elif not isinstance(w_out, BaseArray):
+                raise OperationError(space.w_TypeError, space.wrap( 
+                        'output must be an array'))
+            else:
+                out = w_out
             return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space,
-                                        self, True, promote_to_largest, axis)
+                                        self, True, promote_to_largest, axis,
+                                                                   False, out)
         return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
 
     descr_sum = _reduce_ufunc_impl("add")
@@ -213,6 +223,7 @@
     def descr_dot(self, space, w_other):
         other = convert_to_array(space, w_other)
         if isinstance(other, Scalar):
+            #Note: w_out is not modified, this is numpy compliant.
             return self.descr_mul(space, other)
         elif len(self.shape) < 2 and len(other.shape) < 2:
             w_res = self.descr_mul(space, other)
@@ -514,14 +525,14 @@
             )
         return w_result
 
-    def descr_mean(self, space, w_axis=None):
+    def descr_mean(self, space, w_axis=None, w_out=None):
         if space.is_w(w_axis, space.w_None):
             w_axis = space.wrap(-1)
             w_denom = space.wrap(support.product(self.shape))
         else:
             dim = space.int_w(w_axis)
             w_denom = space.wrap(self.shape[dim])
-        return space.div(self.descr_sum_promote(space, w_axis), w_denom)
+        return space.div(self.descr_sum_promote(space, w_axis, w_out), w_denom)
 
     def descr_var(self, space, w_axis=None):
         return get_appbridge_cache(space).call_method(space, '_var', self,
@@ -714,11 +725,12 @@
     """
     Class for representing virtual arrays, such as binary ops or ufuncs
     """
-    def __init__(self, name, shape, res_dtype):
+    def __init__(self, name, shape, res_dtype, out_arg=None):
         BaseArray.__init__(self, shape)
         self.forced_result = None
         self.res_dtype = res_dtype
         self.name = name
+        self.res = out_arg
         self.size = support.product(self.shape) * res_dtype.get_size()
 
     def _del_sources(self):
@@ -727,13 +739,18 @@
         raise NotImplementedError
 
     def compute(self):
-        ra = ResultArray(self, self.shape, self.res_dtype)
+        ra = ResultArray(self, self.shape, self.res_dtype, self.res)
         loop.compute(ra)
+        if self.res:
+            broadcast_dims = len(self.res.shape) - len(self.shape)
+            chunks = [Chunk(0,0,0,0)] * broadcast_dims + \
+                     [Chunk(0, i, 1, i) for i in self.shape]
+            return Chunks(chunks).apply(self.res)
         return ra.left
 
     def force_if_needed(self):
         if self.forced_result is None:
-            self.forced_result = self.compute()
+            self.forced_result = self.compute().get_concrete()
             self._del_sources()
 
     def get_concrete(self):
@@ -773,8 +790,9 @@
 
 
 class Call1(VirtualArray):
-    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values):
-        VirtualArray.__init__(self, name, shape, res_dtype)
+    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values,
+                                                            out_arg=None):
+        VirtualArray.__init__(self, name, shape, res_dtype, out_arg)
         self.values = values
         self.size = values.size
         self.ufunc = ufunc
@@ -786,6 +804,12 @@
     def create_sig(self):
         if self.forced_result is not None:
             return self.forced_result.create_sig()
+        if self.shape != self.values.shape:
+            #This happens if out arg is used
+            return signature.BroadcastUfunc(self.ufunc, self.name,
+                                            self.calc_dtype,
+                                            self.values.create_sig(),
+                                            self.res.create_sig())
         return signature.Call1(self.ufunc, self.name, self.calc_dtype,
                                self.values.create_sig())
 
@@ -793,8 +817,9 @@
     """
     Intermediate class for performing binary operations.
     """
-    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right):
-        VirtualArray.__init__(self, name, shape, res_dtype)
+    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right,
+            out_arg=None):
+        VirtualArray.__init__(self, name, shape, res_dtype, out_arg)
         self.ufunc = ufunc
         self.left = left
         self.right = right
@@ -832,8 +857,13 @@
         Call2.__init__(self, None, 'assign', shape, dtype, dtype, res, child)
 
     def create_sig(self):
-        return signature.ResultSignature(self.res_dtype, self.left.create_sig(),
-                                         self.right.create_sig())
+        if self.left.shape != self.right.shape:
+            sig = signature.BroadcastResultSignature(self.res_dtype,
+                        self.left.create_sig(), self.right.create_sig())
+        else:
+            sig = signature.ResultSignature(self.res_dtype, 
+                        self.left.create_sig(), self.right.create_sig())
+        return sig
 
 class ToStringArray(Call1):
     def __init__(self, child):
@@ -842,9 +872,9 @@
         self.s = StringBuilder(child.size * self.item_size)
         Call1.__init__(self, None, 'tostring', child.shape, dtype, dtype,
                        child)
-        self.res = W_NDimArray([1], dtype, 'C')
-        self.res_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
-                                    self.res.storage)
+        self.res_str = W_NDimArray([1], dtype, order='C')
+        self.res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
+                                    self.res_str.storage)
 
     def create_sig(self):
         return signature.ToStringSignature(self.calc_dtype,
@@ -950,7 +980,7 @@
 
     def setitem(self, item, value):
         self.invalidated()
-        self.dtype.setitem(self, item, value)
+        self.dtype.setitem(self, item, value.convert_to(self.dtype))
 
     def calc_strides(self, shape):
         dtype = self.find_dtype()
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -28,26 +28,38 @@
         return self.identity
 
     def descr_call(self, space, __args__):
+	from interp_numarray import BaseArray
         args_w, kwds_w = __args__.unpack()
         # it occurs to me that we don't support any datatypes that
         # require casting, change it later when we do
         kwds_w.pop('casting', None)
         w_subok = kwds_w.pop('subok', None)
         w_out = kwds_w.pop('out', space.w_None)
-        if ((w_subok is not None and space.is_true(w_subok)) or
-            not space.is_w(w_out, space.w_None)):
+        # Setup a default value for out
+        if space.is_w(w_out, space.w_None):
+            out = None
+        else:
+            out = w_out
+        if (w_subok is not None and space.is_true(w_subok)):
             raise OperationError(space.w_NotImplementedError,
                                  space.wrap("parameters unsupported"))
         if kwds_w or len(args_w) < self.argcount:
             raise OperationError(space.w_ValueError,
                 space.wrap("invalid number of arguments")
             )
-        elif len(args_w) > self.argcount:
-            # The extra arguments should actually be the output array, but we
-            # don't support that yet.
+        elif (len(args_w) > self.argcount and out is not None) or \
+             (len(args_w) > self.argcount + 1):
             raise OperationError(space.w_TypeError,
                 space.wrap("invalid number of arguments")
             )
+        # Override the default out value, if it has been provided in w_wargs
+        if len(args_w) > self.argcount:
+            out = args_w[-1]
+        else:
+            args_w = args_w[:] + [out]
+        if out is not None and not isinstance(out, BaseArray):
+            raise OperationError(space.w_TypeError, space.wrap(
+                                            'output must be an array'))
         return self.call(space, args_w)
 
     @unwrap_spec(skipna=bool, keepdims=bool)
@@ -105,28 +117,33 @@
         array([[ 1,  5],
                [ 9, 13]])
         """
-        if not space.is_w(w_out, space.w_None):
-            raise OperationError(space.w_NotImplementedError, space.wrap(
-                "out not supported"))
+        from pypy.module.micronumpy.interp_numarray import BaseArray
         if w_axis is None:
             axis = 0
         elif space.is_w(w_axis, space.w_None):
             axis = -1
         else:
             axis = space.int_w(w_axis)
-        return self.reduce(space, w_obj, False, False, axis, keepdims)
+        if space.is_w(w_out, space.w_None):
+            out = None
+        elif not isinstance(w_out, BaseArray):
+            raise OperationError(space.w_TypeError, space.wrap(
+                                                'output must be an array'))
+        else:
+            out = w_out
+        return self.reduce(space, w_obj, False, False, axis, keepdims, out)
 
-    def reduce(self, space, w_obj, multidim, promote_to_largest, dim,
-               keepdims=False):
+    def reduce(self, space, w_obj, multidim, promote_to_largest, axis,
+               keepdims=False, out=None):
         from pypy.module.micronumpy.interp_numarray import convert_to_array, \
-                                                           Scalar, ReduceArray
+                                             Scalar, ReduceArray, W_NDimArray
         if self.argcount != 2:
             raise OperationError(space.w_ValueError, space.wrap("reduce only "
                 "supported for binary functions"))
         assert isinstance(self, W_Ufunc2)
         obj = convert_to_array(space, w_obj)
-        if dim >= len(obj.shape):
-            raise OperationError(space.w_ValueError, space.wrap("axis(=%d) out of bounds" % dim))
+        if axis >= len(obj.shape):
+            raise OperationError(space.w_ValueError, space.wrap("axis(=%d) out of bounds" % axis))
         if isinstance(obj, Scalar):
             raise OperationError(space.w_TypeError, space.wrap("cannot reduce "
                 "on a scalar"))
@@ -144,21 +161,55 @@
         if self.identity is None and size == 0:
             raise operationerrfmt(space.w_ValueError, "zero-size array to "
                     "%s.reduce without identity", self.name)
-        if shapelen > 1 and dim >= 0:
-            return self.do_axis_reduce(obj, dtype, dim, keepdims)
-        arr = ReduceArray(self.func, self.name, self.identity, obj, dtype)
-        return loop.compute(arr)
+        if shapelen > 1 and axis >= 0:
+            if keepdims:
+                shape = obj.shape[:axis] + [1] + obj.shape[axis + 1:]
+            else:
+                shape = obj.shape[:axis] + obj.shape[axis + 1:]
+            if out:
+                #Test for shape agreement
+                if len(out.shape) > len(shape):
+                    raise operationerrfmt(space.w_ValueError,
+                        'output parameter for reduction operation %s' +
+                        ' has too many dimensions', self.name)
+                elif len(out.shape) < len(shape):
+                    raise operationerrfmt(space.w_ValueError,
+                        'output parameter for reduction operation %s' +
+                        ' does not have enough dimensions', self.name)
+                elif out.shape != shape:
+                    raise operationerrfmt(space.w_ValueError,
+                        'output parameter shape mismatch, expecting [%s]' +
+                        ' , got [%s]', 
+                        ",".join([str(x) for x in shape]),
+                        ",".join([str(x) for x in out.shape]),
+                        )
+                #Test for dtype agreement, perhaps create an itermediate
+                #if out.dtype != dtype:
+                #    raise OperationError(space.w_TypeError, space.wrap(
+                #        "mismatched  dtypes"))
+                return self.do_axis_reduce(obj, out.find_dtype(), axis, out)
+            else:
+                result = W_NDimArray(shape, dtype)
+                return self.do_axis_reduce(obj, dtype, axis, result)
+        if out:
+            if len(out.shape)>0:
+                raise operationerrfmt(space.w_ValueError, "output parameter "
+                              "for reduction operation %s has too many"
+                              " dimensions",self.name)
+            arr = ReduceArray(self.func, self.name, self.identity, obj,
+                                                            out.find_dtype())
+            val = loop.compute(arr)
+            assert isinstance(out, Scalar)
+            out.value = val
+        else:
+            arr = ReduceArray(self.func, self.name, self.identity, obj, dtype)
+            val = loop.compute(arr)
+        return val 
 
-    def do_axis_reduce(self, obj, dtype, dim, keepdims):
-        from pypy.module.micronumpy.interp_numarray import AxisReduce,\
-             W_NDimArray
-        if keepdims:
-            shape = obj.shape[:dim] + [1] + obj.shape[dim + 1:]
-        else:
-            shape = obj.shape[:dim] + obj.shape[dim + 1:]
-        result = W_NDimArray(shape, dtype)
+    def do_axis_reduce(self, obj, dtype, axis, result):
+        from pypy.module.micronumpy.interp_numarray import AxisReduce
         arr = AxisReduce(self.func, self.name, self.identity, obj.shape, dtype,
-                         result, obj, dim)
+                         result, obj, axis)
         loop.compute(arr)
         return arr.left
 
@@ -176,24 +227,55 @@
         self.bool_result = bool_result
 
     def call(self, space, args_w):
-        from pypy.module.micronumpy.interp_numarray import (Call1,
-            convert_to_array, Scalar)
-
-        [w_obj] = args_w
+        from pypy.module.micronumpy.interp_numarray import (Call1, BaseArray,
+            convert_to_array, Scalar, shape_agreement)
+        if len(args_w)<2:
+            [w_obj] = args_w
+            out = None
+        else:
+            [w_obj, out] = args_w
+            if space.is_w(out, space.w_None):
+                out = None
         w_obj = convert_to_array(space, w_obj)
         calc_dtype = find_unaryop_result_dtype(space,
                                   w_obj.find_dtype(),
                                   promote_to_float=self.promote_to_float,
                                   promote_bools=self.promote_bools)
-        if self.bool_result:
+        if out:
+            if not isinstance(out, BaseArray):
+                raise OperationError(space.w_TypeError, space.wrap(
+                                                'output must be an array'))
+            res_dtype = out.find_dtype()
+        elif self.bool_result:
             res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
         else:
             res_dtype = calc_dtype
         if isinstance(w_obj, Scalar):
-            return space.wrap(self.func(calc_dtype, w_obj.value.convert_to(calc_dtype)))
-
-        w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype,
-                      w_obj)
+            arr = self.func(calc_dtype, w_obj.value.convert_to(calc_dtype))
+            if isinstance(out,Scalar):
+                out.value=arr
+            elif isinstance(out, BaseArray):
+                out.fill(space, arr)
+            else:
+                out = arr
+            return space.wrap(out)
+        if out:
+            assert isinstance(out, BaseArray) # For translation
+            broadcast_shape =  shape_agreement(space, w_obj.shape, out.shape)
+            if not broadcast_shape or broadcast_shape != out.shape:
+                raise operationerrfmt(space.w_ValueError,
+                    'output parameter shape mismatch, could not broadcast [%s]' +
+                    ' to [%s]', 
+                    ",".join([str(x) for x in w_obj.shape]),
+                    ",".join([str(x) for x in out.shape]),
+                    )
+            w_res = Call1(self.func, self.name, out.shape, calc_dtype,
+                                         res_dtype, w_obj, out)
+            #Force it immediately
+            w_res.get_concrete()
+        else:
+            w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype,
+                                         res_dtype, w_obj)
         w_obj.add_invalidates(w_res)
         return w_res
 
@@ -212,32 +294,61 @@
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call2,
-            convert_to_array, Scalar, shape_agreement)
-
-        [w_lhs, w_rhs] = args_w
+            convert_to_array, Scalar, shape_agreement, BaseArray)
+        if len(args_w)>2:
+            [w_lhs, w_rhs, w_out] = args_w
+        else:
+            [w_lhs, w_rhs] = args_w
+            w_out = None
         w_lhs = convert_to_array(space, w_lhs)
         w_rhs = convert_to_array(space, w_rhs)
-        calc_dtype = find_binop_result_dtype(space,
-            w_lhs.find_dtype(), w_rhs.find_dtype(),
-            int_only=self.int_only,
-            promote_to_float=self.promote_to_float,
-            promote_bools=self.promote_bools,
-        )
+        if space.is_w(w_out, space.w_None) or w_out is None:
+            out = None
+            calc_dtype = find_binop_result_dtype(space,
+                w_lhs.find_dtype(), w_rhs.find_dtype(),
+                int_only=self.int_only,
+                promote_to_float=self.promote_to_float,
+                promote_bools=self.promote_bools,
+            )
+        elif not isinstance(w_out, BaseArray):
+            raise OperationError(space.w_TypeError, space.wrap(
+                    'output must be an array'))
+        else:
+            out = w_out
+            calc_dtype = out.find_dtype()
         if self.comparison_func:
             res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
         else:
             res_dtype = calc_dtype
         if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
-            return space.wrap(self.func(calc_dtype,
+            arr = self.func(calc_dtype,
                 w_lhs.value.convert_to(calc_dtype),
                 w_rhs.value.convert_to(calc_dtype)
-            ))
+            )
+            if isinstance(out,Scalar):
+                out.value=arr
+            elif isinstance(out, BaseArray):
+                out.fill(space, arr)
+            else:
+                out = arr
+            return space.wrap(out)
         new_shape = shape_agreement(space, w_lhs.shape, w_rhs.shape)
+        # Test correctness of out.shape
+        if out and out.shape != shape_agreement(space, new_shape, out.shape):
+            raise operationerrfmt(space.w_ValueError,
+                'output parameter shape mismatch, could not broadcast [%s]' +
+                ' to [%s]', 
+                ",".join([str(x) for x in new_shape]),
+                ",".join([str(x) for x in out.shape]),
+                )
         w_res = Call2(self.func, self.name,
                       new_shape, calc_dtype,
-                      res_dtype, w_lhs, w_rhs)
+                      res_dtype, w_lhs, w_rhs, out)
         w_lhs.add_invalidates(w_res)
         w_rhs.add_invalidates(w_res)
+        if out:
+            #out.add_invalidates(w_res) #causes a recursion loop
+            w_res.get_concrete()
         return w_res
 
 
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -216,13 +216,14 @@
         return self.child.eval(frame, arr.child)
 
 class Call1(Signature):
-    _immutable_fields_ = ['unfunc', 'name', 'child', 'dtype']
+    _immutable_fields_ = ['unfunc', 'name', 'child', 'res', 'dtype']
 
-    def __init__(self, func, name, dtype, child):
+    def __init__(self, func, name, dtype, child, res=None):
         self.unfunc = func
         self.child = child
         self.name = name
         self.dtype = dtype
+        self.res  = res
 
     def hash(self):
         return compute_hash(self.name) ^ intmask(self.child.hash() << 1)
@@ -256,6 +257,29 @@
         v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype)
         return self.unfunc(arr.calc_dtype, v)
 
+
+class BroadcastUfunc(Call1):
+    def _invent_numbering(self, cache, allnumbers):
+        self.res._invent_numbering(cache, allnumbers)
+        self.child._invent_numbering(new_cache(), allnumbers)
+
+    def debug_repr(self):
+        return 'BroadcastUfunc(%s, %s)' % (self.name, self.child.debug_repr())
+
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import Call1
+
+        assert isinstance(arr, Call1)
+        vtransforms = transforms + [BroadcastTransform(arr.values.shape)]
+        self.child._create_iter(iterlist, arraylist, arr.values, vtransforms)
+        self.res._create_iter(iterlist, arraylist, arr.res, transforms)
+
+    def eval(self, frame, arr):
+        from pypy.module.micronumpy.interp_numarray import Call1
+        assert isinstance(arr, Call1)
+        v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype)
+        return self.unfunc(arr.calc_dtype, v)
+
 class Call2(Signature):
     _immutable_fields_ = ['binfunc', 'name', 'calc_dtype', 'left', 'right']
 
@@ -316,7 +340,17 @@
 
         assert isinstance(arr, ResultArray)
         offset = frame.get_final_iter().offset
-        arr.left.setitem(offset, self.right.eval(frame, arr.right))
+        val = self.right.eval(frame, arr.right)
+        arr.left.setitem(offset, val)
+
+class BroadcastResultSignature(ResultSignature):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import ResultArray
+
+        assert isinstance(arr, ResultArray)
+        rtransforms = transforms + [BroadcastTransform(arr.left.shape)]
+        self.left._create_iter(iterlist, arraylist, arr.left, transforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
 
 class ToStringSignature(Call1):
     def __init__(self, dtype, child):
@@ -327,10 +361,10 @@
         from pypy.module.micronumpy.interp_numarray import ToStringArray
 
         assert isinstance(arr, ToStringArray)
-        arr.res.setitem(0, self.child.eval(frame, arr.values).convert_to(
+        arr.res_str.setitem(0, self.child.eval(frame, arr.values).convert_to(
             self.dtype))
         for i in range(arr.item_size):
-            arr.s.append(arr.res_casted[i])
+            arr.s.append(arr.res_str_casted[i])
 
 class BroadcastLeft(Call2):
     def _invent_numbering(self, cache, allnumbers):
@@ -455,6 +489,5 @@
             cur = arr.left.getitem(iterator.offset)
             value = self.binfunc(self.calc_dtype, cur, v)
         arr.left.setitem(iterator.offset, value)
-    
     def debug_repr(self):
         return 'AxisReduceSig(%s, %s)' % (self.name, self.right.debug_repr())
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -995,6 +995,10 @@
         assert a.sum() == 5
 
         raises(TypeError, 'a.sum(2, 3)')
+        d = array(0.)
+        b = a.sum(out=d)
+        assert b == d
+        assert isinstance(b, float)
 
     def test_reduce_nd(self):
         from numpypy import arange, array, multiply
@@ -1495,8 +1499,6 @@
         a = array([[1, 2], [3, 4], [5, 6], [7, 8],
                    [9, 10], [11, 12], [13, 14]])
         b = a[::2]
-        print a
-        print b
         assert (b == [[1, 2], [5, 6], [9, 10], [13, 14]]).all()
         c = b + b
         assert c[1][1] == 12
diff --git a/pypy/module/micronumpy/test/test_outarg.py b/pypy/module/micronumpy/test/test_outarg.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_outarg.py
@@ -0,0 +1,126 @@
+import py
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+class AppTestOutArg(BaseNumpyAppTest):
+    def test_reduce_out(self):
+        from numpypy import arange, zeros, array
+        a = arange(15).reshape(5, 3)
+        b = arange(12).reshape(4,3)
+        c = a.sum(0, out=b[1])
+        assert (c == [30, 35, 40]).all()
+        assert (c == b[1]).all()
+        raises(ValueError, 'a.prod(0, out=arange(10))')
+        a=arange(12).reshape(3,2,2)
+        raises(ValueError, 'a.sum(0, out=arange(12).reshape(3,2,2))')
+        raises(ValueError, 'a.sum(0, out=arange(3))')
+        c = array([-1, 0, 1]).sum(out=zeros([], dtype=bool))
+        #You could argue that this should product False, but
+        # that would require an itermediate result. Cpython numpy
+        # gives True.
+        assert c == True
+        a = array([[-1, 0, 1], [1, 0, -1]])
+        c = a.sum(0, out=zeros((3,), dtype=bool))
+        assert (c == [True, False, True]).all()
+        c = a.sum(1, out=zeros((2,), dtype=bool))
+        assert (c == [True, True]).all()
+
+    def test_reduce_intermediary(self):
+        from numpypy import arange, array
+        a = arange(15).reshape(5, 3)
+        b = array(range(3), dtype=bool)
+        c = a.prod(0, out=b)
+        assert(b == [False,  True,  True]).all()
+
+    def test_ufunc_out(self):
+        from _numpypy import array, negative, zeros, sin
+        from math import sin as msin
+        a = array([[1, 2], [3, 4]])
+        c = zeros((2,2,2))
+        b = negative(a + a, out=c[1])
+        #test for view, and also test that forcing out also forces b
+        assert (c[:, :, 1] == [[0, 0], [-4, -8]]).all()
+        assert (b == [[-2, -4], [-6, -8]]).all()
+        #Test broadcast, type promotion
+        b = negative(3, out=a)
+        assert (a == -3).all()
+        c = zeros((2, 2), dtype=float)
+        b = negative(3, out=c)
+        assert b.dtype.kind == c.dtype.kind
+        assert b.shape == c.shape
+        a = array([1, 2])
+        b = sin(a, out=c)
+        assert(c == [[msin(1), msin(2)]] * 2).all()
+        b = sin(a, out=c+c)
+        assert (c == b).all()
+
+        #Test shape agreement
+        a = zeros((3,4))
+        b = zeros((3,5))
+        raises(ValueError, 'negative(a, out=b)')
+        b = zeros((1,4))
+        raises(ValueError, 'negative(a, out=b)')
+
+    def test_binfunc_out(self):
+        from _numpypy import array, add
+        a = array([[1, 2], [3, 4]])
+        out = array([[1, 2], [3, 4]])
+        c = add(a, a, out=out)
+        assert (c == out).all()
+        assert c.shape == a.shape
+        assert c.dtype is a.dtype
+        c[0,0] = 100
+        assert out[0, 0] == 100
+        out[:] = 100
+        raises(ValueError, 'c = add(a, a, out=out[1])')
+        c = add(a[0], a[1], out=out[1])
+        assert (c == out[1]).all()
+        assert (c == [4, 6]).all()
+        assert (out[0] == 100).all()
+        c = add(a[0], a[1], out=out)
+        assert (c == out[1]).all()
+        assert (c == out[0]).all()
+        out = array(16, dtype=int)
+        b = add(10, 10, out=out)
+        assert b==out
+        assert b.dtype == out.dtype
+        
+    def test_applevel(self):
+        from _numpypy import array, sum, max, min
+        a = array([[1, 2], [3, 4]])
+        out = array([[0, 0], [0, 0]])
+        c = sum(a, axis=0, out=out[0])
+        assert (c == [4, 6]).all()
+        assert (c == out[0]).all()
+        assert (c != out[1]).all()
+        c = max(a, axis=1, out=out[0])
+        assert (c == [2, 4]).all()
+        assert (c == out[0]).all()
+        assert (c != out[1]).all()
+        
+    def test_ufunc_cast(self):
+        from _numpypy import array, negative, add, sum
+        a = array(16, dtype = int)
+        c = array(0, dtype = float)
+        b = negative(a, out=c)
+        assert b == c
+        b = add(a, a, out=c)
+        assert b == c
+        d = array([16, 16], dtype=int)
+        b = sum(d, out=c)
+        assert b == c
+        try:
+            from _numpypy import version
+            v = version.version.split('.')
+        except:
+            v = ['1', '6', '0'] # numpypy is api compatable to what version?
+        if v[0]<'2':
+            b = negative(c, out=a)
+            assert b == a
+            b = add(c, c, out=a)
+            assert b == a
+            b = sum(array([16, 16], dtype=float), out=a)
+            assert b == a
+        else:
+            cast_error = raises(TypeError, negative, c, a)
+            assert str(cast_error.value) == \
+            "Cannot cast ufunc negative output from dtype('float64') to dtype('int64') with casting rule 'same_kind'"
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -131,7 +131,7 @@
         #            bogus. We need to improve the situation somehow.
         self.check_simple_loop({'getinteriorfield_raw': 2,
                                 'setinteriorfield_raw': 1,
-                                'arraylen_gc': 1,
+                                'arraylen_gc': 2,
                                 'guard_true': 1,
                                 'int_lt': 1,
                                 'jump': 1,
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
@@ -128,3 +128,82 @@
         loop, = log.loops_by_filename(self.filepath)
         ops = loop.ops_by_id('look')
         assert 'call' not in log.opnames(ops)
+
+    #XXX the following tests only work with strategies enabled
+
+    def test_should_not_create_intobject_with_sets(self):
+        def main(n):
+            i = 0
+            s = set()
+            while i < n:
+                s.add(i)
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
+
+    def test_should_not_create_stringobject_with_sets(self):
+        def main(n):
+            i = 0
+            s = set()
+            while i < n:
+                s.add(str(i))
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
+
+    def test_should_not_create_intobject_with_lists(self):
+        def main(n):
+            i = 0
+            l = []
+            while i < n:
+                l.append(i)
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
+
+    def test_should_not_create_stringobject_with_lists(self):
+        def main(n):
+            i = 0
+            l = []
+            while i < n:
+                l.append(str(i))
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
+
+    def test_optimized_create_list_from_string(self):
+        def main(n):
+            i = 0
+            l = []
+            while i < n:
+                l = list("abc" * i)
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
+
+    def test_optimized_create_set_from_list(self):
+        def main(n):
+            i = 0
+            while i < n:
+                s = set([1,2,3])
+                i += 1
+        log = self.run(main, [1000])
+        assert log.result == main(1000)
+        loop, = log.loops_by_filename(self.filepath)
+        opnames = log.opnames(loop.allops())
+        assert opnames.count('new_with_vtable') == 0
diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -1,6 +1,6 @@
 from __future__ import with_statement
 import new
-import py
+import py, sys
 from pypy.objspace.flow.model import Constant, Block, Link, Variable
 from pypy.objspace.flow.model import mkentrymap, c_last_exception
 from pypy.interpreter.argument import Arguments
@@ -893,6 +893,8 @@
         """ Tests code generated by pypy-c compiled with BUILD_LIST_FROM_ARG
         bytecode
         """
+        if sys.version_info < (2, 7):
+            py.test.skip("2.7 only test")
         self.patch_opcodes('BUILD_LIST_FROM_ARG')
         try:
             def f():
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -111,9 +111,15 @@
     length = len(data)
     start, stop, step, slicelength = w_slice.indices4(space, length)
     assert slicelength >= 0
-    newdata = [data[start + i*step] for i in range(slicelength)]
+    if step == 1 and 0 <= start <= stop:
+        newdata = data[start:stop]
+    else:
+        newdata = _getitem_slice_multistep(data, start, step, slicelength)
     return W_BytearrayObject(newdata)
 
+def _getitem_slice_multistep(data, start, step, slicelength):
+    return [data[start + i*step] for i in range(slicelength)]
+
 def contains__Bytearray_Int(space, w_bytearray, w_char):
     char = space.int_w(w_char)
     if not 0 <= char < 256:
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -127,10 +127,10 @@
     def iter(self, w_dict):
         return ModuleDictIteratorImplementation(self.space, self, w_dict)
 
-    def keys(self, w_dict):
+    def w_keys(self, w_dict):
         space = self.space
-        iterator = self.unerase(w_dict.dstorage).iteritems
-        return [space.wrap(key) for key, cell in iterator()]
+        l = self.unerase(w_dict.dstorage).keys()
+        return space.newlist_str(l)
 
     def values(self, w_dict):
         iterator = self.unerase(w_dict.dstorage).itervalues
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
@@ -90,9 +90,9 @@
 def _add_indirections():
     dict_methods = "setitem setitem_str getitem \
                     getitem_str delitem length \
-                    clear keys values \
+                    clear w_keys values \
                     items iter setdefault \
-                    popitem".split()
+                    popitem listview_str listview_int".split()
 
     def make_method(method):
         def f(self, *args):
@@ -113,7 +113,7 @@
     def get_empty_storage(self):
         raise NotImplementedError
 
-    def keys(self, w_dict):
+    def w_keys(self, w_dict):
         iterator = self.iter(w_dict)
         result = []
         while 1:
@@ -121,7 +121,7 @@
             if w_key is not None:
                 result.append(w_key)
             else:
-                return result
+                return self.space.newlist(result)
 
     def values(self, w_dict):
         iterator = self.iter(w_dict)
@@ -160,6 +160,11 @@
         w_dict.strategy = strategy
         w_dict.dstorage = storage
 
+    def listview_str(self, w_dict):
+        return None
+
+    def listview_int(self, w_dict):
+        return None
 
 class EmptyDictStrategy(DictStrategy):
 
@@ -371,8 +376,9 @@
             self.switch_to_object_strategy(w_dict)
             return w_dict.getitem(w_key)
 
-    def keys(self, w_dict):
-        return [self.wrap(key) for key in self.unerase(w_dict.dstorage).iterkeys()]
+    def w_keys(self, w_dict):
+        l = [self.wrap(key) for key in self.unerase(w_dict.dstorage).iterkeys()]
+        return self.space.newlist(l)
 
     def values(self, w_dict):
         return self.unerase(w_dict.dstorage).values()
@@ -425,8 +431,8 @@
     def iter(self, w_dict):
         return ObjectIteratorImplementation(self.space, self, w_dict)
 
-    def keys(self, w_dict):
-        return self.unerase(w_dict.dstorage).keys()
+    def w_keys(self, w_dict):
+        return self.space.newlist(self.unerase(w_dict.dstorage).keys())
 
 
 class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
@@ -469,9 +475,15 @@
         assert key is not None
         return self.unerase(w_dict.dstorage).get(key, None)
 
+    def listview_str(self, w_dict):
+        return self.unerase(w_dict.dstorage).keys()
+
     def iter(self, w_dict):
         return StrIteratorImplementation(self.space, self, w_dict)
 
+    def w_keys(self, w_dict):
+        return self.space.newlist_str(self.listview_str(w_dict))
+
 
 class _WrappedIteratorMixin(object):
     _mixin_ = True
@@ -534,6 +546,14 @@
     def iter(self, w_dict):
         return IntIteratorImplementation(self.space, self, w_dict)
 
+    def listview_int(self, w_dict):
+        return self.unerase(w_dict.dstorage).keys()
+
+    def w_keys(self, w_dict):
+        # XXX there is no space.newlist_int yet
+        space = self.space
+        return space.call_function(space.w_list, w_dict)
+
 class IntIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
     pass
 
@@ -688,7 +708,7 @@
     return space.newlist(w_self.items())
 
 def dict_keys__DictMulti(space, w_self):
-    return space.newlist(w_self.keys())
+    return w_self.w_keys()
 
 def dict_values__DictMulti(space, w_self):
     return space.newlist(w_self.values())
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -76,7 +76,7 @@
 
     def keys(self, w_dict):
         space = self.space
-        return [space.wrap(key) for key in self.unerase(w_dict.dstorage).dict_w.iterkeys()]
+        return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys())
 
     def values(self, w_dict):
         return [unwrap_cell(self.space, w_value) for w_value in self.unerase(w_dict.dstorage).dict_w.itervalues()]
diff --git a/pypy/objspace/std/dicttype.py b/pypy/objspace/std/dicttype.py
--- a/pypy/objspace/std/dicttype.py
+++ b/pypy/objspace/std/dicttype.py
@@ -62,8 +62,14 @@
         w_fill = space.w_None
     if space.is_w(w_type, space.w_dict):
         w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
-        for w_key in space.listview(w_keys):
-            w_dict.setitem(w_key, w_fill)
+
+        strlist = space.listview_str(w_keys)
+        if strlist is not None:
+            for key in strlist:
+                w_dict.setitem_str(key, w_fill)
+        else:
+            for w_key in space.listview(w_keys):
+                w_dict.setitem(w_key, w_fill)
     else:
         w_dict = space.call_function(w_type)
         for w_key in space.listview(w_keys):
diff --git a/pypy/objspace/std/frozensettype.py b/pypy/objspace/std/frozensettype.py
--- a/pypy/objspace/std/frozensettype.py
+++ b/pypy/objspace/std/frozensettype.py
@@ -39,13 +39,11 @@
 def descr__frozenset__new__(space, w_frozensettype,
                             w_iterable=gateway.NoneNotWrapped):
     from pypy.objspace.std.setobject import W_FrozensetObject
-    from pypy.objspace.std.setobject import make_setdata_from_w_iterable
     if (space.is_w(w_frozensettype, space.w_frozenset) and
         w_iterable is not None and type(w_iterable) is W_FrozensetObject):
         return w_iterable
     w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
-    data = make_setdata_from_w_iterable(space, w_iterable)
-    W_FrozensetObject.__init__(w_obj, space, data)
+    W_FrozensetObject.__init__(w_obj, space, w_iterable)
     return w_obj
 
 frozenset_typedef = StdTypeDef("frozenset",
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -29,9 +29,8 @@
 class W_SeqIterObject(W_AbstractSeqIterObject):
     """Sequence iterator implementation for general sequences."""
 
-class W_FastListIterObject(W_AbstractSeqIterObject):
-    """Sequence iterator specialized for lists, accessing directly their
-    RPython-level list of wrapped objects.
+class W_FastListIterObject(W_AbstractSeqIterObject): # XXX still needed
+    """Sequence iterator specialized for lists.
     """
 
 class W_FastTupleIterObject(W_AbstractSeqIterObject):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -139,6 +139,16 @@
         new erased object as storage"""
         self.strategy.init_from_list_w(self, list_w)
 
+    def clear(self, space):
+        """Initializes (or overrides) the listobject as empty."""
+        self.space = space
+        if space.config.objspace.std.withliststrategies:
+            strategy = space.fromcache(EmptyListStrategy)
+        else:
+            strategy = space.fromcache(ObjectListStrategy)
+        self.strategy = strategy
+        strategy.clear(self)
+
     def clone(self):
         """Returns a clone by creating a new listobject
         with the same strategy and a copy of the storage"""
@@ -200,6 +210,11 @@
         """ Return the items in the list as unwrapped strings. If the list does
         not use the list strategy, return None. """
         return self.strategy.getitems_str(self)
+
+    def getitems_int(self):
+        """ Return the items in the list as unwrapped ints. If the list does
+        not use the list strategy, return None. """
+        return self.strategy.getitems_int(self)
     # ___________________________________________________
 
 
@@ -300,6 +315,9 @@
     def getitems_str(self, w_list):
         return None
 
+    def getitems_int(self, w_list):
+        return None
+
     def getstorage_copy(self, w_list):
         raise NotImplementedError
 
@@ -358,6 +376,9 @@
         assert len(list_w) == 0
         w_list.lstorage = self.erase(None)
 
+    def clear(self, w_list):
+        w_list.lstorage = self.erase(None)
+
     erase, unerase = rerased.new_erasing_pair("empty")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -516,6 +537,9 @@
             raise IndexError
         return start + i * step
 
+    def getitems_int(self, w_list):
+        return self._getitems_range(w_list, False)
+
     def getitem(self, w_list, i):
         return self.wrap(self._getitem_unwrapped(w_list, i))
 
@@ -696,6 +720,7 @@
             for i in l:
                 if i == obj:
                     return True
+            return False
         return ListStrategy.contains(self, w_list, w_obj)
 
     def length(self, w_list):
@@ -937,6 +962,9 @@
     def init_from_list_w(self, w_list, list_w):
         w_list.lstorage = self.erase(list_w)
 
+    def clear(self, w_list):
+        w_list.lstorage = self.erase([])
+
     def contains(self, w_list, w_obj):
         return ListStrategy.contains(self, w_list, w_obj)
 
@@ -970,6 +998,9 @@
         if reverse:
             l.reverse()
 
+    def getitems_int(self, w_list):
+        return self.unerase(w_list.lstorage)
+
 class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = 0.0
     _applevel_repr = "float"
@@ -1027,37 +1058,49 @@
     def getitems_str(self, w_list):
         return self.unerase(w_list.lstorage)
 
-
 # _______________________________________________________
 
 init_signature = Signature(['sequence'], None, None)
 init_defaults = [None]
 
 def init__List(space, w_list, __args__):
-    from pypy.objspace.std.tupleobject import W_TupleObject
+    from pypy.objspace.std.tupleobject import W_AbstractTupleObject
     # this is on the silly side
     w_iterable, = __args__.parse_obj(
             None, 'list', init_signature, init_defaults)
-    w_list.__init__(space, [])
+    w_list.clear(space)
     if w_iterable is not None:
-        # unfortunately this is duplicating space.unpackiterable to avoid
-        # assigning a new RPython list to 'wrappeditems', which defeats the
-        # W_FastListIterObject optimization.
-        if isinstance(w_iterable, W_ListObject):
-            w_list.extend(w_iterable)
-        elif isinstance(w_iterable, W_TupleObject):
-            w_list.extend(W_ListObject(space, w_iterable.wrappeditems[:]))
-        else:
-            _init_from_iterable(space, w_list, w_iterable)
+        if type(w_iterable) is W_ListObject:
+            w_iterable.copy_into(w_list)
+            return
+        elif isinstance(w_iterable, W_AbstractTupleObject):
+            w_list.__init__(space, w_iterable.getitems_copy())
+            return
+
+        intlist = space.listview_int(w_iterable)
+        if intlist is not None:
+            w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
+             # need to copy because intlist can share with w_iterable
+            w_list.lstorage = strategy.erase(intlist[:])
+            return
+
+        strlist = space.listview_str(w_iterable)
+        if strlist is not None:
+            w_list.strategy = strategy = space.fromcache(StringListStrategy)
+             # need to copy because intlist can share with w_iterable
+            w_list.lstorage = strategy.erase(strlist[:])
+            return
+
+        # xxx special hack for speed
+        from pypy.interpreter.generator import GeneratorIterator
+        if isinstance(w_iterable, GeneratorIterator):
+            w_iterable.unpack_into_w(w_list)
+            return
+        # /xxx
+        _init_from_iterable(space, w_list, w_iterable)
 
 def _init_from_iterable(space, w_list, w_iterable):
     # in its own function to make the JIT look into init__List
-    # xxx special hack for speed
-    from pypy.interpreter.generator import GeneratorIterator
-    if isinstance(w_iterable, GeneratorIterator):
-        w_iterable.unpack_into_w(w_list)
-        return
-    # /xxx
     w_iterator = space.iter(w_iterable)
     while True:
         try:
diff --git a/pypy/objspace/std/listtype.py b/pypy/objspace/std/listtype.py
--- a/pypy/objspace/std/listtype.py
+++ b/pypy/objspace/std/listtype.py
@@ -43,7 +43,7 @@
 def descr__new__(space, w_listtype, __args__):
     from pypy.objspace.std.listobject import W_ListObject
     w_obj = space.allocate_instance(W_ListObject, w_listtype)
-    W_ListObject.__init__(w_obj, space, [])
+    w_obj.clear(space)
     return w_obj
 
 # ____________________________________________________________
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -694,6 +694,8 @@
         self.delitem(w_dict, w_key)
         return (w_key, w_value)
 
+    # XXX could implement a more efficient w_keys based on space.newlist_str
+
 def materialize_r_dict(space, obj, dict_w):
     map = obj._get_mapdict_map()
     new_obj = map.materialize_r_dict(space, obj, dict_w)
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -227,10 +227,7 @@
             return W_ComplexObject(x.real, x.imag)
 
         if isinstance(x, set):
-            rdict_w = r_dict(self.eq_w, self.hash_w)
-            for item in x:
-                rdict_w[self.wrap(item)] = None
-            res = W_SetObject(self, rdict_w)
+            res = W_SetObject(self, self.newlist([self.wrap(item) for item in x]))
             return res
 
         if isinstance(x, frozenset):
@@ -325,7 +322,7 @@
 
     def newset(self):
         from pypy.objspace.std.setobject import newset
-        return W_SetObject(self, newset(self))
+        return W_SetObject(self, None)
 
     def newslice(self, w_start, w_end, w_step):
         return W_SliceObject(w_start, w_end, w_step)
@@ -403,7 +400,7 @@
     def unpackiterable(self, w_obj, expected_length=-1):
         if isinstance(w_obj, W_AbstractTupleObject):
             t = w_obj.getitems_copy()
-        elif isinstance(w_obj, W_ListObject):
+        elif type(w_obj) is W_ListObject:
             t = w_obj.getitems_copy()
         else:
             return ObjSpace.unpackiterable(self, w_obj, expected_length)
@@ -417,7 +414,7 @@
         """
         if isinstance(w_obj, W_AbstractTupleObject):
             t = w_obj.tolist()
-        elif isinstance(w_obj, W_ListObject):
+        elif type(w_obj) is W_ListObject:
             if unroll:
                 t = w_obj.getitems_unroll()
             else:
@@ -438,7 +435,7 @@
         return self.fixedview(w_obj, expected_length, unroll=True)
 
     def listview(self, w_obj, expected_length=-1):
-        if isinstance(w_obj, W_ListObject):
+        if type(w_obj) is W_ListObject:
             t = w_obj.getitems()
         elif isinstance(w_obj, W_AbstractTupleObject):
             t = w_obj.getitems_copy()
@@ -449,8 +446,25 @@
         return t
 
     def listview_str(self, w_obj):
-        if isinstance(w_obj, W_ListObject):
+        # note: uses exact type checking for objects with strategies,
+        # and isinstance() for others.  See test_listobject.test_uses_custom...
+        if type(w_obj) is W_ListObject:
             return w_obj.getitems_str()
+        if type(w_obj) is W_DictMultiObject:
+            return w_obj.listview_str()
+        if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
+            return w_obj.listview_str()
+        if isinstance(w_obj, W_StringObject):
+            return w_obj.listview_str()
+        return None
+
+    def listview_int(self, w_obj):
+        if type(w_obj) is W_ListObject:
+            return w_obj.getitems_int()
+        if type(w_obj) is W_DictMultiObject:
+            return w_obj.listview_int()
+        if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
+            return w_obj.listview_int()
         return None
 
     def sliceindices(self, w_slice, w_length):
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -7,6 +7,12 @@
 from pypy.interpreter.argument import Signature
 from pypy.objspace.std.settype import set_typedef as settypedef
 from pypy.objspace.std.frozensettype import frozenset_typedef as frozensettypedef
+from pypy.rlib import rerased
+from pypy.rlib.objectmodel import instantiate
+from pypy.interpreter.generator import GeneratorIterator
+from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.intobject import W_IntObject
+from pypy.objspace.std.stringobject import W_StringObject
 
 class W_BaseSetObject(W_Object):
     typedef = None
@@ -20,88 +26,859 @@
             return True
         return False
 
-
-    def __init__(w_self, space, setdata):
+    def __init__(w_self, space, w_iterable=None):
         """Initialize the set by taking ownership of 'setdata'."""
-        assert setdata is not None
-        w_self.setdata = setdata
+        w_self.space = space
+        set_strategy_and_setdata(space, w_self, w_iterable)
 
     def __repr__(w_self):
         """representation for debugging purposes"""
-        reprlist = [repr(w_item) for w_item in w_self.setdata.keys()]
+        reprlist = [repr(w_item) for w_item in w_self.getkeys()]
         return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
 
+    def from_storage_and_strategy(w_self, storage, strategy):
+        obj = w_self._newobj(w_self.space, None)
+        assert isinstance(obj, W_BaseSetObject)
+        obj.strategy = strategy
+        obj.sstorage = storage
+        return obj
+
     _lifeline_ = None
     def getweakref(self):
         return self._lifeline_
+
     def setweakref(self, space, weakreflifeline):
         self._lifeline_ = weakreflifeline
     def delweakref(self):
         self._lifeline_ = None
 
+    def switch_to_object_strategy(self, space):
+        d = self.strategy.getdict_w(self)
+        self.strategy = strategy = space.fromcache(ObjectSetStrategy)
+        self.sstorage = strategy.erase(d)
+
+    def switch_to_empty_strategy(self):
+        self.strategy = strategy = self.space.fromcache(EmptySetStrategy)
+        self.sstorage = strategy.get_empty_storage()
+
+    # _____________ strategy methods ________________
+
+
+    def clear(self):
+        """ Removes all elements from the set. """
+        self.strategy.clear(self)
+
+    def copy_real(self):
+        """ Returns a clone of the set. Frozensets storages are also copied."""
+        return self.strategy.copy_real(self)
+
+    def length(self):
+        """ Returns the number of items inside the set. """
+        return self.strategy.length(self)
+
+    def add(self, w_key):
+        """ Adds an element to the set. The element must be wrapped. """
+        self.strategy.add(self, w_key)
+
+    def remove(self, w_item):
+        """ Removes the given element from the set. Element must be wrapped. """
+        return self.strategy.remove(self, w_item)
+
+    def getdict_w(self):
+        """ Returns a dict with all elements of the set. Needed only for switching to ObjectSetStrategy. """
+        return self.strategy.getdict_w(self)
+
+    def listview_str(self):
+        """ If this is a string set return its contents as a list of uwnrapped strings. Otherwise return None. """
+        return self.strategy.listview_str(self)
+
+    def listview_int(self):
+        """ If this is an int set return its contents as a list of uwnrapped ints. Otherwise return None. """
+        return self.strategy.listview_int(self)
+
+    def get_storage_copy(self):
+        """ Returns a copy of the storage. Needed when we want to clone all elements from one set and
+        put them into another. """
+        return self.strategy.get_storage_copy(self)
+
+    def getkeys(self):
+        """ Returns a list of all elements inside the set. Only used in __repr__. Use as less as possible."""
+        return self.strategy.getkeys(self)
+
+    def difference(self, w_other):
+        """ Returns a set with all items that are in this set, but not in w_other. W_other must be a set."""
+        return self.strategy.difference(self, w_other)
+
+    def difference_update(self, w_other):
+        """ As difference but overwrites the sets content with the result. W_other must be a set."""
+        self.strategy.difference_update(self, w_other)
+
+    def symmetric_difference(self, w_other):
+        """ Returns a set with all items that are either in this set or in w_other, but not in both. W_other must be a set. """
+        return self.strategy.symmetric_difference(self, w_other)
+
+    def symmetric_difference_update(self, w_other):
+        """ As symmetric_difference but overwrites the content of the set with the result. W_other must be a set."""
+        self.strategy.symmetric_difference_update(self, w_other)
+
+    def intersect(self, w_other):
+        """ Returns a set with all items that exists in both sets, this set and in w_other. W_other must be a set. """
+        return self.strategy.intersect(self, w_other)
+
+    def intersect_update(self, w_other):
+        """ Keeps only those elements found in both sets, removing all other elements. W_other must be a set."""
+        self.strategy.intersect_update(self, w_other)
+
+    def issubset(self, w_other):
+        """ Checks wether this set is a subset of w_other. W_other must be a set. """
+        return self.strategy.issubset(self, w_other)
+
+    def isdisjoint(self, w_other):
+        """ Checks wether this set and the w_other are completly different, i.e. have no equal elements. W_other must be a set."""
+        return self.strategy.isdisjoint(self, w_other)
+
+    def update(self, w_other):
+        """ Appends all elements from the given set to this set. W_other must be a set."""
+        self.strategy.update(self, w_other)
+
+    def has_key(self, w_key):
+        """ Checks wether this set contains the given wrapped key."""
+        return self.strategy.has_key(self, w_key)
+
+    def equals(self, w_other):
+        """ Checks wether this set and the given set are equal, i.e. contain the same elements. W_other must be a set."""
+        return self.strategy.equals(self, w_other)
+
+    def iter(self):
+        """ Returns an iterator of the elements from this set. """
+        return self.strategy.iter(self)
+
+    def popitem(self):
+        """ Removes an arbitrary element from the set. May raise KeyError if set is empty."""
+        return self.strategy.popitem(self)
+
 class W_SetObject(W_BaseSetObject):
     from pypy.objspace.std.settype import set_typedef as typedef
 
-    def _newobj(w_self, space, rdict_w):
-        """Make a new set by taking ownership of 'rdict_w'."""
+    def _newobj(w_self, space, w_iterable):
+        """Make a new set by taking ownership of 'w_iterable'."""
         if type(w_self) is W_SetObject:
-            return W_SetObject(space, rdict_w)
+            return W_SetObject(space, w_iterable)
         w_type = space.type(w_self)
         w_obj = space.allocate_instance(W_SetObject, w_type)
-        W_SetObject.__init__(w_obj, space, rdict_w)
+        W_SetObject.__init__(w_obj, space, w_iterable)
         return w_obj
 
 class W_FrozensetObject(W_BaseSetObject):
     from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
     hash = 0
 
-    def _newobj(w_self, space, rdict_w):
-        """Make a new frozenset by taking ownership of 'rdict_w'."""
+    def _newobj(w_self, space, w_iterable):
+        """Make a new frozenset by taking ownership of 'w_iterable'."""
         if type(w_self) is W_FrozensetObject:
-            return W_FrozensetObject(space, rdict_w)
+            return W_FrozensetObject(space, w_iterable)
         w_type = space.type(w_self)
         w_obj = space.allocate_instance(W_FrozensetObject, w_type)
-        W_FrozensetObject.__init__(w_obj, space, rdict_w)
+        W_FrozensetObject.__init__(w_obj, space, w_iterable)
         return w_obj
 
 registerimplementation(W_BaseSetObject)
 registerimplementation(W_SetObject)
 registerimplementation(W_FrozensetObject)
 
-class W_SetIterObject(W_Object):
-    from pypy.objspace.std.settype import setiter_typedef as typedef
+class SetStrategy(object):
+    def __init__(self, space):
+        self.space = space
 
-    def __init__(w_self, setdata):
-        w_self.content = content = setdata
-        w_self.len = len(content)
-        w_self.pos = 0
-        w_self.iterator = w_self.content.iterkeys()
+    def get_empty_dict(self):
+        """ Returns an empty dictionary depending on the strategy. Used to initalize a new storage. """
+        raise NotImplementedError
 
-    def next_entry(w_self):
-        for w_key in w_self.iterator:
+    def get_empty_storage(self):
+        """ Returns an empty storage (erased) object. Used to initialize an empty set."""
+        raise NotImplementedError
+
+    def listview_str(self, w_set):
+        return None
+
+    def listview_int(self, w_set):
+        return None
+
+    #def erase(self, storage):
+    #    raise NotImplementedError
+
+    #def unerase(self, storage):
+    #    raise NotImplementedError
+
+    # __________________ methods called on W_SetObject _________________
+
+    def clear(self, w_set):
+        raise NotImplementedError
+
+    def copy_real(self, w_set):
+        raise NotImplementedError
+
+    def length(self, w_set):
+        raise NotImplementedError
+
+    def add(self, w_set, w_key):
+        raise NotImplementedError
+
+    def remove(self, w_set, w_item):
+        raise NotImplementedError
+
+    def getdict_w(self, w_set):
+        raise NotImplementedError
+
+    def get_storage_copy(self, w_set):
+        raise NotImplementedError
+
+    def getkeys(self, w_set):
+        raise NotImplementedError
+
+    def difference(self, w_set, w_other):
+        raise NotImplementedError
+
+    def difference_update(self, w_set, w_other):
+        raise NotImplementedError
+
+    def symmetric_difference(self, w_set, w_other):
+        raise NotImplementedError
+
+    def symmetric_difference_update(self, w_set, w_other):
+        raise NotImplementedError
+
+    def intersect(self, w_set, w_other):
+        raise NotImplementedError
+
+    def intersect_update(self, w_set, w_other):
+        raise NotImplementedError
+
+    def issubset(self, w_set, w_other):
+        raise NotImplementedError
+
+    def isdisjoint(self, w_set, w_other):
+        raise NotImplementedError
+
+    def update(self, w_set, w_other):
+        raise NotImplementedError
+
+    def has_key(self, w_set, w_key):
+        raise NotImplementedError
+
+    def equals(self, w_set, w_other):
+        raise NotImplementedError
+
+    def iter(self, w_set):
+        raise NotImplementedError
+
+    def popitem(self, w_set):
+        raise NotImplementedError
+
+class EmptySetStrategy(SetStrategy):
+
+    erase, unerase = rerased.new_erasing_pair("empty")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def get_empty_storage(self):
+        return self.erase(None)
+
+    def is_correct_type(self, w_key):
+        return False
+
+    def length(self, w_set):
+        return 0
+
+    def clear(self, w_set):
+        pass
+
+    def copy_real(self, w_set):
+        storage = self.erase(None)
+        clone = w_set.from_storage_and_strategy(storage, self)
+        return clone
+
+    def add(self, w_set, w_key):
+        if type(w_key) is W_IntObject:
+            strategy = self.space.fromcache(IntegerSetStrategy)
+        elif type(w_key) is W_StringObject:
+            strategy = self.space.fromcache(StringSetStrategy)
+        else:
+            strategy = self.space.fromcache(ObjectSetStrategy)
+        w_set.strategy = strategy
+        w_set.sstorage = strategy.get_empty_storage()
+        w_set.add(w_key)
+
+    def remove(self, w_set, w_item):
+        return False
+
+    def getdict_w(self, w_set):
+        return newset(self.space)
+
+    def get_storage_copy(self, w_set):
+        return w_set.sstorage
+
+    def getkeys(self, w_set):
+        return []
+
+    def has_key(self, w_set, w_key):
+        return False
+
+    def equals(self, w_set, w_other):
+        if w_other.strategy is self or w_other.length() == 0:
+            return True
+        return False
+
+    def difference(self, w_set, w_other):
+        return w_set.copy_real()
+
+    def difference_update(self, w_set, w_other):
+        pass
+
+    def intersect(self, w_set, w_other):
+        return w_set.copy_real()
+
+    def intersect_update(self, w_set, w_other):
+        pass
+
+    def isdisjoint(self, w_set, w_other):
+        return True
+
+    def issubset(self, w_set, w_other):
+        return True
+
+    def symmetric_difference(self, w_set, w_other):
+        return w_other.copy_real()
+
+    def symmetric_difference_update(self, w_set, w_other):
+        w_set.strategy = w_other.strategy
+        w_set.sstorage = w_other.get_storage_copy()
+
+    def update(self, w_set, w_other):
+        w_set.strategy = w_other.strategy
+        w_set.sstorage = w_other.get_storage_copy()
+
+    def iter(self, w_set):
+        return EmptyIteratorImplementation(self.space, w_set)
+
+    def popitem(self, w_set):
+        raise OperationError(self.space.w_KeyError,
+                                self.space.wrap('pop from an empty set'))
+
+class AbstractUnwrappedSetStrategy(object):
+    _mixin_ = True
+
+    def is_correct_type(self, w_key):
+        """ Checks wether the given wrapped key fits this strategy."""
+        raise NotImplementedError
+
+    def unwrap(self, w_item):
+        """ Returns the unwrapped value of the given wrapped item."""
+        raise NotImplementedError
+
+    def wrap(self, item):
+        """ Returns a wrapped version of the given unwrapped item. """
+        raise NotImplementedError
+
+    def get_storage_from_list(self, list_w):
+        setdata = self.get_empty_dict()
+        for w_item in list_w:
+            setdata[self.unwrap(w_item)] = None
+        return self.erase(setdata)
+
+    def get_storage_from_unwrapped_list(self, items):
+        setdata = self.get_empty_dict()
+        for item in items:
+            setdata[item] = None
+        return self.erase(setdata)
+
+    def length(self, w_set):
+        return len(self.unerase(w_set.sstorage))
+
+    def clear(self, w_set):
+        w_set.switch_to_empty_strategy()
+
+    def copy_real(self, w_set):
+        # may be used internally on frozen sets, although frozenset().copy()
+        # returns self in frozenset_copy__Frozenset.
+        strategy = w_set.strategy
+        d = self.unerase(w_set.sstorage)
+        storage = self.erase(d.copy())
+        clone = w_set.from_storage_and_strategy(storage, strategy)
+        return clone
+
+    def add(self, w_set, w_key):
+        if self.is_correct_type(w_key):
+            d = self.unerase(w_set.sstorage)
+            d[self.unwrap(w_key)] = None
+        else:
+            w_set.switch_to_object_strategy(self.space)
+            w_set.add(w_key)
+
+    def remove(self, w_set, w_item):
+        from pypy.objspace.std.dictmultiobject import _never_equal_to_string
+        d = self.unerase(w_set.sstorage)
+        if not self.is_correct_type(w_item):
+            #XXX check type of w_item and immediately return False in some cases
+            w_set.switch_to_object_strategy(self.space)
+            return w_set.remove(w_item)
+
+        key = self.unwrap(w_item)
+        try:
+            del d[key]
+            return True
+        except KeyError:
+            return False
+
+    def getdict_w(self, w_set):
+        result = newset(self.space)
+        keys = self.unerase(w_set.sstorage).keys()
+        for key in keys:
+            result[self.wrap(key)] = None
+        return result
+
+    def get_storage_copy(self, w_set):
+        d = self.unerase(w_set.sstorage)
+        copy = self.erase(d.copy())
+        return copy
+
+    def getkeys(self, w_set):
+        keys = self.unerase(w_set.sstorage).keys()
+        keys_w = [self.wrap(key) for key in keys]
+        return keys_w
+
+    def has_key(self, w_set, w_key):
+        from pypy.objspace.std.dictmultiobject import _never_equal_to_string
+        if not self.is_correct_type(w_key):
+            #XXX check type of w_item and immediately return False in some cases
+            w_set.switch_to_object_strategy(self.space)
+            return w_set.has_key(w_key)
+        d = self.unerase(w_set.sstorage)
+        return self.unwrap(w_key) in d
+
+    def equals(self, w_set, w_other):
+        if w_set.length() != w_other.length():
+            return False
+        items = self.unerase(w_set.sstorage).keys()
+        for key in items:
+            if not w_other.has_key(self.wrap(key)):
+                return False
+        return True
+
+    def _difference_wrapped(self, w_set, w_other):
+        strategy = self.space.fromcache(ObjectSetStrategy)
+
+        d_new = strategy.get_empty_dict()
+        for obj in self.unerase(w_set.sstorage):
+            w_item = self.wrap(obj)
+            if not w_other.has_key(w_item):
+                d_new[w_item] = None
+
+        return strategy.erase(d_new)
+
+    def _difference_unwrapped(self, w_set, w_other):
+        iterator = self.unerase(w_set.sstorage).iterkeys()
+        other_dict = self.unerase(w_other.sstorage)
+        result_dict = self.get_empty_dict()
+        for key in iterator:
+            if key not in other_dict:
+                result_dict[key] = None
+        return self.erase(result_dict)
+
+    def _difference_base(self, w_set, w_other):
+        if self is w_other.strategy:
+            strategy = w_set.strategy
+            storage = self._difference_unwrapped(w_set, w_other)
+        elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+            strategy = w_set.strategy
+            storage = w_set.sstorage
+        else:
+            strategy = self.space.fromcache(ObjectSetStrategy)
+            storage = self._difference_wrapped(w_set, w_other)
+        return storage, strategy
+
+    def difference(self, w_set, w_other):
+        storage, strategy = self._difference_base(w_set, w_other)
+        w_newset = w_set.from_storage_and_strategy(storage, strategy)
+        return w_newset
+
+    def difference_update(self, w_set, w_other):
+        storage, strategy = self._difference_base(w_set, w_other)
+        w_set.strategy = strategy
+        w_set.sstorage = storage
+
+    def _symmetric_difference_unwrapped(self, w_set, w_other):
+        d_new = self.get_empty_dict()
+        d_this = self.unerase(w_set.sstorage)
+        d_other = self.unerase(w_other.sstorage)
+        for key in d_other.keys():
+            if not key in d_this:
+                d_new[key] = None
+        for key in d_this.keys():
+            if not key in d_other:
+                d_new[key] = None
+
+        storage = self.erase(d_new)
+        return storage
+
+    def _symmetric_difference_wrapped(self, w_set, w_other):
+        newsetdata = newset(self.space)
+        for obj in self.unerase(w_set.sstorage):
+            w_item = self.wrap(obj)
+            if not w_other.has_key(w_item):
+                newsetdata[w_item] = None
+
+        w_iterator = w_other.iter()
+        while True:
+            w_item = w_iterator.next_entry()
+            if w_item is None:
+                break
+            if not w_set.has_key(w_item):
+                newsetdata[w_item] = None
+
+        strategy = self.space.fromcache(ObjectSetStrategy)
+        return strategy.erase(newsetdata)
+
+    def _symmetric_difference_base(self, w_set, w_other):
+        if self is w_other.strategy:
+            strategy = w_set.strategy
+            storage = self._symmetric_difference_unwrapped(w_set, w_other)
+        else:
+            strategy = self.space.fromcache(ObjectSetStrategy)
+            storage = self._symmetric_difference_wrapped(w_set, w_other)
+        return storage, strategy
+
+    def symmetric_difference(self, w_set, w_other):
+        storage, strategy = self._symmetric_difference_base(w_set, w_other)
+        return w_set.from_storage_and_strategy(storage, strategy)
+
+    def symmetric_difference_update(self, w_set, w_other):
+        storage, strategy = self._symmetric_difference_base(w_set, w_other)
+        w_set.strategy = strategy
+        w_set.sstorage = storage
+
+    def _intersect_base(self, w_set, w_other):
+        if self is w_other.strategy:
+            strategy = w_set.strategy
+            storage = strategy._intersect_unwrapped(w_set, w_other)
+        elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+            strategy = self.space.fromcache(EmptySetStrategy)
+            storage = strategy.get_empty_storage()
+        else:
+            strategy = self.space.fromcache(ObjectSetStrategy)
+            storage = self._intersect_wrapped(w_set, w_other)
+        return storage, strategy
+
+    def _intersect_wrapped(self, w_set, w_other):
+        result = newset(self.space)
+        for key in self.unerase(w_set.sstorage):
+            w_key = self.wrap(key)
+            if w_other.has_key(w_key):
+                result[w_key] = None
+
+        strategy = self.space.fromcache(ObjectSetStrategy)
+        return strategy.erase(result)
+
+    def _intersect_unwrapped(self, w_set, w_other):
+        result = self.get_empty_dict()
+        d_this = self.unerase(w_set.sstorage)
+        d_other = self.unerase(w_other.sstorage)
+        for key in d_this:
+            if key in d_other:
+                result[key] = None
+        return self.erase(result)
+
+    def intersect(self, w_set, w_other):
+        if w_set.length() > w_other.length():
+            return w_other.intersect(w_set)
+
+        storage, strategy = self._intersect_base(w_set, w_other)
+        return w_set.from_storage_and_strategy(storage, strategy)
+
+    def intersect_update(self, w_set, w_other):
+        if w_set.length() > w_other.length():
+            w_intersection = w_other.intersect(w_set)
+            strategy = w_intersection.strategy
+            storage = w_intersection.sstorage
+        else:
+            storage, strategy = self._intersect_base(w_set, w_other)
+        w_set.strategy = strategy
+        w_set.sstorage = storage
+
+    def _issubset_unwrapped(self, w_set, w_other):
+        d_other = self.unerase(w_other.sstorage)
+        for item in self.unerase(w_set.sstorage):
+            if not item in d_other:
+                return False
+        return True
+
+    def _issubset_wrapped(self, w_set, w_other):
+        for obj in self.unerase(w_set.sstorage):
+            w_item = self.wrap(obj)
+            if not w_other.has_key(w_item):
+                return False
+        return True
+
+    def issubset(self, w_set, w_other):
+        if w_set.length() == 0:
+            return True
+
+        if w_set.strategy is w_other.strategy:
+            return self._issubset_unwrapped(w_set, w_other)
+        elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+            return False
+        else:
+            return self._issubset_wrapped(w_set, w_other)
+
+    def _isdisjoint_unwrapped(self, w_set, w_other):
+        d_set = self.unerase(w_set.sstorage)
+        d_other = self.unerase(w_other.sstorage)
+        for key in d_set:
+            if key in d_other:
+                return False
+        return True
+
+    def _isdisjoint_wrapped(self, w_set, w_other):
+        d = self.unerase(w_set.sstorage)
+        for key in d:
+            if w_other.has_key(self.wrap(key)):
+                return False
+        return True
+
+    def isdisjoint(self, w_set, w_other):
+        if w_other.length() == 0:
+            return True
+        if w_set.length() > w_other.length():
+            return w_other.isdisjoint(w_set)
+
+        if w_set.strategy is w_other.strategy:
+            return self._isdisjoint_unwrapped(w_set, w_other)
+        elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+            return True
+        else:
+            return self._isdisjoint_wrapped(w_set, w_other)
+
+    def update(self, w_set, w_other):
+        if self is w_other.strategy:
+            d_set = self.unerase(w_set.sstorage)
+            d_other = self.unerase(w_other.sstorage)
+            d_set.update(d_other)
+            return
+
+        w_set.switch_to_object_strategy(self.space)
+        w_set.update(w_other)
+
+    def popitem(self, w_set):
+        storage = self.unerase(w_set.sstorage)
+        try:
+            # this returns a tuple because internally sets are dicts
+            result = storage.popitem()
+        except KeyError:
+            # strategy may still be the same even if dict is empty
+            raise OperationError(self.space.w_KeyError,
+                            self.space.wrap('pop from an empty set'))
+        return self.wrap(result[0])
+
+class StringSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+    erase, unerase = rerased.new_erasing_pair("string")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def get_empty_storage(self):
+        return self.erase({})
+
+    def get_empty_dict(self):
+        return {}
+
+    def listview_str(self, w_set):
+        return self.unerase(w_set.sstorage).keys()
+
+    def is_correct_type(self, w_key):
+        return type(w_key) is W_StringObject
+
+    def may_contain_equal_elements(self, strategy):
+        if strategy is self.space.fromcache(IntegerSetStrategy):
+            return False
+        if strategy is self.space.fromcache(EmptySetStrategy):
+            return False
+        return True
+
+    def unwrap(self, w_item):
+        return self.space.str_w(w_item)
+
+    def wrap(self, item):
+        return self.space.wrap(item)
+
+    def iter(self, w_set):
+        return StringIteratorImplementation(self.space, self, w_set)
+
+class IntegerSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+    erase, unerase = rerased.new_erasing_pair("integer")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def get_empty_storage(self):
+        return self.erase({})
+
+    def get_empty_dict(self):
+        return {}
+
+    def listview_int(self, w_set):
+        return self.unerase(w_set.sstorage).keys()
+
+    def is_correct_type(self, w_key):
+        from pypy.objspace.std.intobject import W_IntObject
+        return type(w_key) is W_IntObject
+
+    def may_contain_equal_elements(self, strategy):
+        if strategy is self.space.fromcache(StringSetStrategy):
+            return False
+        if strategy is self.space.fromcache(EmptySetStrategy):
+            return False
+        return True
+
+    def unwrap(self, w_item):
+        return self.space.int_w(w_item)
+
+    def wrap(self, item):
+        return self.space.wrap(item)
+
+    def iter(self, w_set):
+        return IntegerIteratorImplementation(self.space, self, w_set)
+
+class ObjectSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+    erase, unerase = rerased.new_erasing_pair("object")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def get_empty_storage(self):
+        return self.erase(self.get_empty_dict())
+
+    def get_empty_dict(self):
+        return newset(self.space)
+
+    def is_correct_type(self, w_key):
+        return True
+
+    def may_contain_equal_elements(self, strategy):
+        if strategy is self.space.fromcache(EmptySetStrategy):
+            return False
+        return True
+
+    def unwrap(self, w_item):
+        return w_item
+
+    def wrap(self, item):
+        return item
+
+    def iter(self, w_set):
+        return RDictIteratorImplementation(self.space, self, w_set)
+
+    def update(self, w_set, w_other):
+        d_obj = self.unerase(w_set.sstorage)
+        w_iterator = w_other.iter()
+        while True:
+            w_item = w_iterator.next_entry()
+            if w_item is None:
+                break
+            d_obj[w_item] = None
+
+class IteratorImplementation(object):
+    def __init__(self, space, implementation):
+        self.space = space
+        self.setimplementation = implementation
+        self.len = implementation.length()
+        self.pos = 0
+
+    def next(self):
+        if self.setimplementation is None:
+            return None
+        if self.len != self.setimplementation.length():
+            self.len = -1   # Make this error state sticky
+            raise OperationError(self.space.w_RuntimeError,
+                     self.space.wrap("set changed size during iteration"))
+        # look for the next entry
+        if self.pos < self.len:
+            result = self.next_entry()
+            self.pos += 1
+            return result
+        # no more entries
+        self.setimplementation = None
+        return None
+
+    def next_entry(self):
+        """ Purely abstract method
+        """
+        raise NotImplementedError
+
+    def length(self):
+        if self.setimplementation is not None:
+            return self.len - self.pos
+        return 0
+
+class EmptyIteratorImplementation(IteratorImplementation):
+    def next_entry(self):
+        return None
+
+
+class StringIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, strategy, w_set):
+        IteratorImplementation.__init__(self, space, w_set)
+        d = strategy.unerase(w_set.sstorage)
+        self.iterator = d.iterkeys()
+
+    def next_entry(self):
+        for key in self.iterator:
+            return self.space.wrap(key)
+        else:
+            return None
+
+class IntegerIteratorImplementation(IteratorImplementation):
+    #XXX same implementation in dictmultiobject on dictstrategy-branch
+    def __init__(self, space, strategy, dictimplementation):
+        IteratorImplementation.__init__(self, space, dictimplementation)
+        d = strategy.unerase(dictimplementation.sstorage)
+        self.iterator = d.iterkeys()
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        for key in self.iterator:
+            return self.space.wrap(key)
+        else:
+            return None
+
+class RDictIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, strategy, dictimplementation):
+        IteratorImplementation.__init__(self, space, dictimplementation)
+        d = strategy.unerase(dictimplementation.sstorage)
+        self.iterator = d.iterkeys()
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        for w_key in self.iterator:
             return w_key
         else:
             return None
 
+class W_SetIterObject(W_Object):
+    from pypy.objspace.std.settype import setiter_typedef as typedef
+    # XXX this class should be killed, and the various
+    # iterimplementations should be W_Objects directly.
+
+    def __init__(w_self, space, iterimplementation):
+        w_self.space = space
+        w_self.iterimplementation = iterimplementation
+
 registerimplementation(W_SetIterObject)
 
 def iter__SetIterObject(space, w_setiter):
     return w_setiter
 
 def next__SetIterObject(space, w_setiter):
-    content = w_setiter.content
-    if content is not None:
-        if w_setiter.len != len(content):
-            w_setiter.len = -1   # Make this error state sticky
-            raise OperationError(space.w_RuntimeError,
-                     space.wrap("Set changed size during iteration"))
-        # look for the next entry
-        w_result = w_setiter.next_entry()
-        if w_result is not None:
-            w_setiter.pos += 1
-            return w_result
-        # no more entries
-        w_setiter.content = None
+    iterimplementation = w_setiter.iterimplementation
+    w_key = iterimplementation.next()
+    if w_key is not None:
+        return w_key
     raise OperationError(space.w_StopIteration, space.w_None)
 
 # XXX __length_hint__()
@@ -116,107 +893,91 @@
 def newset(space):
     return r_dict(space.eq_w, space.hash_w, force_non_null=True)
 
-def make_setdata_from_w_iterable(space, w_iterable=None):
-    """Return a new r_dict with the content of w_iterable."""
+def set_strategy_and_setdata(space, w_set, w_iterable):
+    from pypy.objspace.std.intobject import W_IntObject
+    if w_iterable is None :
+        w_set.strategy = strategy = space.fromcache(EmptySetStrategy)
+        w_set.sstorage = strategy.get_empty_storage()
+        return
+
     if isinstance(w_iterable, W_BaseSetObject):
-        return w_iterable.setdata.copy()
-    data = newset(space)
-    if w_iterable is not None:
-        for w_item in space.listview(w_iterable):
-            data[w_item] = None
-    return data
+        w_set.strategy = w_iterable.strategy
+        w_set.sstorage = w_iterable.get_storage_copy()
+        return
+
+    stringlist = space.listview_str(w_iterable)
+    if stringlist is not None:
+        strategy = space.fromcache(StringSetStrategy)
+        w_set.strategy = strategy
+        w_set.sstorage = strategy.get_storage_from_unwrapped_list(stringlist)
+        return
+
+    intlist = space.listview_int(w_iterable)
+    if intlist is not None:
+        strategy = space.fromcache(IntegerSetStrategy)
+        w_set.strategy = strategy
+        w_set.sstorage = strategy.get_storage_from_unwrapped_list(intlist)
+        return
+
+    iterable_w = space.listview(w_iterable)
+
+    if len(iterable_w) == 0:
+        w_set.strategy = strategy = space.fromcache(EmptySetStrategy)
+        w_set.sstorage = strategy.get_empty_storage()
+        return
+
+    _pick_correct_strategy(space, w_set, iterable_w)
+
+def _pick_correct_strategy(space, w_set, iterable_w):
+    # check for integers
+    for w_item in iterable_w:
+        if type(w_item) is not W_IntObject:
+            break
+    else:
+        w_set.strategy = space.fromcache(IntegerSetStrategy)
+        w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
+        return
+
+    # check for strings
+    for w_item in iterable_w:
+        if type(w_item) is not W_StringObject:
+            break
+    else:
+        w_set.strategy = space.fromcache(StringSetStrategy)
+        w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
+        return
+
+    w_set.strategy = space.fromcache(ObjectSetStrategy)
+    w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
 
 def _initialize_set(space, w_obj, w_iterable=None):
-    w_obj.setdata.clear()
-    if w_iterable is not None:
-        w_obj.setdata = make_setdata_from_w_iterable(space, w_iterable)
+    w_obj.clear()
+    set_strategy_and_setdata(space, w_obj, w_iterable)
 
 def _convert_set_to_frozenset(space, w_obj):
-    if space.isinstance_w(w_obj, space.w_set):
-        return W_FrozensetObject(space,
-                                 make_setdata_from_w_iterable(space, w_obj))
+    if isinstance(w_obj, W_SetObject):
+        w_frozen = W_FrozensetObject(space, None)
+        w_frozen.strategy = w_obj.strategy
+        w_frozen.sstorage = w_obj.sstorage
+        return w_frozen
+    elif space.isinstance_w(w_obj, space.w_set):
+        w_frz = space.allocate_instance(W_FrozensetObject, space.w_frozenset)
+        W_FrozensetObject.__init__(w_frz, space, w_obj)
+        return w_frz
     else:
         return None
 
-# helper functions for set operation on dicts
-
-def _is_eq(ld, rd):
-    if len(ld) != len(rd):
-        return False
-    for w_key in ld:
-        if w_key not in rd:
-            return False
-    return True
-
-def _difference_dict(space, ld, rd):
-    result = newset(space)
-    for w_key in ld:
-        if w_key not in rd:
-            result[w_key] = None
-    return result
-
-def _difference_dict_update(space, ld, rd):
-    if ld is rd:
-        ld.clear()     # for the case 'a.difference_update(a)'
-    else:
-        for w_key in rd:
-            try:
-                del ld[w_key]
-            except KeyError:
-                pass
-
-def _intersection_dict(space, ld, rd):
-    result = newset(space)
-    if len(ld) > len(rd):
-        ld, rd = rd, ld     # loop over the smaller dict
-    for w_key in ld:
-        if w_key in rd:
-            result[w_key] = None
-    return result
-
-def _isdisjoint_dict(ld, rd):
-    if len(ld) > len(rd):
-        ld, rd = rd, ld     # loop over the smaller dict
-    for w_key in ld:
-        if w_key in rd:
-            return False
-    return True
-
-def _symmetric_difference_dict(space, ld, rd):
-    result = newset(space)
-    for w_key in ld:
-        if w_key not in rd:
-            result[w_key] = None
-    for w_key in rd:
-        if w_key not in ld:
-            result[w_key] = None
-    return result
-
-def _issubset_dict(ldict, rdict):
-    if len(ldict) > len(rdict):
-        return False
-
-    for w_key in ldict:
-        if w_key not in rdict:
-            return False
-    return True
-
-
-#end helper functions
-
 def set_update__Set(space, w_left, others_w):
     """Update a set with the union of itself and another."""
-    ld = w_left.setdata
     for w_other in others_w:
         if isinstance(w_other, W_BaseSetObject):
-            ld.update(w_other.setdata)     # optimization only
+            w_left.update(w_other)     # optimization only
         else:
             for w_key in space.listview(w_other):
-                ld[w_key] = None
+                w_left.add(w_key)
 
 def inplace_or__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    ld.update(rd)
+    w_left.update(w_other)
     return w_left
 
 inplace_or__Set_Frozenset = inplace_or__Set_Set
@@ -226,10 +987,10 @@
 
     This has no effect if the element is already present.
     """
-    w_left.setdata[w_other] = None
+    w_left.add(w_other)
 
 def set_copy__Set(space, w_set):
-    return w_set._newobj(space, w_set.setdata.copy())
+    return w_set.copy_real()
 
 def frozenset_copy__Frozenset(space, w_left):
     if type(w_left) is W_FrozensetObject:
@@ -238,63 +999,51 @@
         return set_copy__Set(space, w_left)
 
 def set_clear__Set(space, w_left):
-    w_left.setdata.clear()
+    w_left.clear()
 
 def sub__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _difference_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    return w_left.difference(w_other)
 
 sub__Set_Frozenset = sub__Set_Set
 sub__Frozenset_Set = sub__Set_Set
 sub__Frozenset_Frozenset = sub__Set_Set
 
 def set_difference__Set(space, w_left, others_w):
-    result = w_left.setdata
-    if len(others_w) == 0:
-        result = result.copy()
-    for w_other in others_w:
-        if isinstance(w_other, W_BaseSetObject):
-            rd = w_other.setdata     # optimization only
-        else:
-            rd = make_setdata_from_w_iterable(space, w_other)
-        result = _difference_dict(space, result, rd)
-    return w_left._newobj(space, result)
+    result = w_left.copy_real()
+    set_difference_update__Set(space, result, others_w)
+    return result
 
 frozenset_difference__Frozenset = set_difference__Set
 
 
 def set_difference_update__Set(space, w_left, others_w):
-    ld = w_left.setdata
     for w_other in others_w:
         if isinstance(w_other, W_BaseSetObject):
             # optimization only
-            _difference_dict_update(space, ld, w_other.setdata)
+            w_left.difference_update(w_other)
         else:
-            for w_key in space.listview(w_other):
-                try:
-                    del ld[w_key]
-                except KeyError:
-                    pass
+            w_other_as_set = w_left._newobj(space, w_other)
+            w_left.difference_update(w_other_as_set)
 
 def inplace_sub__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    _difference_dict_update(space, ld, rd)
+    w_left.difference_update(w_other)
     return w_left
 
 inplace_sub__Set_Frozenset = inplace_sub__Set_Set
 
 def eq__Set_Set(space, w_left, w_other):
     # optimization only (the general case is eq__Set_settypedef)
-    return space.wrap(_is_eq(w_left.setdata, w_other.setdata))
+    return space.wrap(w_left.equals(w_other))
 
 eq__Set_Frozenset = eq__Set_Set
 eq__Frozenset_Frozenset = eq__Set_Set
 eq__Frozenset_Set = eq__Set_Set
 
 def eq__Set_settypedef(space, w_left, w_other):
-    rd = make_setdata_from_w_iterable(space, w_other)
-    return space.wrap(_is_eq(w_left.setdata, rd))
+    # tested in test_buildinshortcut.py
+    #XXX do not make new setobject here
+    w_other_as_set = w_left._newobj(space, w_other)
+    return space.wrap(w_left.equals(w_other_as_set))
 
 eq__Set_frozensettypedef = eq__Set_settypedef
 eq__Frozenset_settypedef = eq__Set_settypedef
@@ -308,15 +1057,16 @@
 eq__Frozenset_ANY = eq__Set_ANY
 
 def ne__Set_Set(space, w_left, w_other):
-    return space.wrap(not _is_eq(w_left.setdata, w_other.setdata))
+    return space.wrap(not w_left.equals(w_other))
 
 ne__Set_Frozenset = ne__Set_Set
 ne__Frozenset_Frozenset = ne__Set_Set
 ne__Frozenset_Set = ne__Set_Set
 
 def ne__Set_settypedef(space, w_left, w_other):
-    rd = make_setdata_from_w_iterable(space, w_other)
-    return space.wrap(not _is_eq(w_left.setdata, rd))
+    #XXX this is not tested
+    w_other_as_set = w_left._newobj(space, w_other)
+    return space.wrap(not w_left.equals(w_other_as_set))
 
 ne__Set_frozensettypedef = ne__Set_settypedef
 ne__Frozenset_settypedef = ne__Set_settypedef
@@ -331,12 +1081,12 @@
 
 def contains__Set_ANY(space, w_left, w_other):
     try:
-        return space.newbool(w_other in w_left.setdata)
+        return space.newbool(w_left.has_key(w_other))
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             w_f = _convert_set_to_frozenset(space, w_other)
             if w_f is not None:
-                return space.newbool(w_f in w_left.setdata)
+                return space.newbool(w_left.has_key(w_f))
         raise
 
 contains__Frozenset_ANY = contains__Set_ANY
@@ -345,19 +1095,23 @@
     # optimization only (the general case works too)
     if space.is_w(w_left, w_other):
         return space.w_True
-    ld, rd = w_left.setdata, w_other.setdata
-    return space.wrap(_issubset_dict(ld, rd))
+    if w_left.length() > w_other.length():
+        return space.w_False
+    return space.wrap(w_left.issubset(w_other))
 
 set_issubset__Set_Frozenset = set_issubset__Set_Set
 frozenset_issubset__Frozenset_Set = set_issubset__Set_Set
 frozenset_issubset__Frozenset_Frozenset = set_issubset__Set_Set
 
 def set_issubset__Set_ANY(space, w_left, w_other):
-    if space.is_w(w_left, w_other):
-        return space.w_True
+    # not checking whether w_left is w_other here, because if that were the
+    # case the more precise multimethod would have applied.
 
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    return space.wrap(_issubset_dict(ld, rd))
+    w_other_as_set = w_left._newobj(space, w_other)
+
+    if w_left.length() > w_other_as_set.length():
+        return space.w_False
+    return space.wrap(w_left.issubset(w_other_as_set))
 
 frozenset_issubset__Frozenset_ANY = set_issubset__Set_ANY
 
@@ -370,9 +1124,9 @@
     # optimization only (the general case works too)
     if space.is_w(w_left, w_other):
         return space.w_True
-
-    ld, rd = w_left.setdata, w_other.setdata
-    return space.wrap(_issubset_dict(rd, ld))
+    if w_left.length() < w_other.length():
+        return space.w_False
+    return space.wrap(w_other.issubset(w_left))
 
 set_issuperset__Set_Frozenset = set_issuperset__Set_Set
 set_issuperset__Frozenset_Set = set_issuperset__Set_Set
@@ -382,8 +1136,11 @@
     if space.is_w(w_left, w_other):
         return space.w_True
 
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    return space.wrap(_issubset_dict(rd, ld))
+    w_other_as_set = w_left._newobj(space, w_other)
+
+    if w_left.length() < w_other_as_set.length():
+        return space.w_False
+    return space.wrap(w_other_as_set.issubset(w_left))
 
 frozenset_issuperset__Frozenset_ANY = set_issuperset__Set_ANY
 
@@ -395,7 +1152,7 @@
 # automatic registration of "lt(x, y)" as "not ge(y, x)" would not give the
 # correct answer here!
 def lt__Set_Set(space, w_left, w_other):
-    if len(w_left.setdata) >= len(w_other.setdata):
+    if w_left.length() >= w_other.length():
         return space.w_False
     else:
         return le__Set_Set(space, w_left, w_other)
@@ -405,7 +1162,7 @@
 lt__Frozenset_Frozenset = lt__Set_Set
 
 def gt__Set_Set(space, w_left, w_other):
-    if len(w_left.setdata) <= len(w_other.setdata):
+    if w_left.length() <= w_other.length():
         return space.w_False
     else:
         return ge__Set_Set(space, w_left, w_other)
@@ -421,26 +1178,19 @@
     Returns True if successfully removed.
     """
     try:
-        del w_left.setdata[w_item]
-        return True
-    except KeyError:
-        return False
+        deleted = w_left.remove(w_item)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
-        w_f = _convert_set_to_frozenset(space, w_item)
-        if w_f is None:
-            raise
+        else:
+            w_f = _convert_set_to_frozenset(space, w_item)
+            if w_f is None:
+                raise
+            deleted = w_left.remove(w_f)
 
-    try:
-        del w_left.setdata[w_f]
-        return True
-    except KeyError:
-        return False
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-        return False
+    if w_left.length() == 0:
+        w_left.switch_to_empty_strategy()
+    return deleted
 
 def set_discard__Set_ANY(space, w_left, w_item):
     _discard_from_set(space, w_left, w_item)
@@ -454,8 +1204,12 @@
     if w_set.hash != 0:
         return space.wrap(w_set.hash)
     hash = r_uint(1927868237)
-    hash *= r_uint(len(w_set.setdata) + 1)
-    for w_item in w_set.setdata:
+    hash *= r_uint(w_set.length() + 1)
+    w_iterator = w_set.iter()
+    while True:
+        w_item = w_iterator.next_entry()
+        if w_item is None:
+            break
         h = space.hash_w(w_item)
         value = (r_uint(h ^ (h << 16) ^ 89869747)  * multi)
         hash = hash ^ value
@@ -468,71 +1222,75 @@
     return space.wrap(hash)
 
 def set_pop__Set(space, w_left):
-    try:
-        w_key, _ = w_left.setdata.popitem()
-    except KeyError:
-        raise OperationError(space.w_KeyError,
-                                space.wrap('pop from an empty set'))
-    return w_key
+    return w_left.popitem()
 
 def and__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _intersection_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    new_set = w_left.intersect(w_other)
+    return new_set
 
 and__Set_Frozenset = and__Set_Set
 and__Frozenset_Set = and__Set_Set
 and__Frozenset_Frozenset = and__Set_Set
 
-def _intersection_multiple(space, w_left, others_w):
-    result = w_left.setdata
-    for w_other in others_w:
+def set_intersection__Set(space, w_left, others_w):
+    #XXX find smarter implementations
+    others_w = [w_left] + others_w
+
+    # find smallest set in others_w to reduce comparisons
+    startindex, startlength = 0, -1
+    for i in range(len(others_w)):
+        w_other = others_w[i]
+        try:
+            length = space.int_w(space.len(w_other))
+        except OperationError, e:
+            if (e.match(space, space.w_TypeError) or
+                e.match(space, space.w_AttributeError)):
+                continue
+            raise
+
+        if startlength == -1 or length < startlength:
+            startindex = i
+            startlength = length
+
+    others_w[startindex], others_w[0] = others_w[0], others_w[startindex]
+
+    result = w_left._newobj(space, others_w[0])
+    for i in range(1,len(others_w)):
+        w_other = others_w[i]
         if isinstance(w_other, W_BaseSetObject):
             # optimization only
-            result = _intersection_dict(space, result, w_other.setdata)
+            result.intersect_update(w_other)
         else:
-            result2 = newset(space)
-            for w_key in space.listview(w_other):
-                if w_key in result:
-                    result2[w_key] = None
-            result = result2
+            w_other_as_set = w_left._newobj(space, w_other)
+            result.intersect_update(w_other_as_set)
     return result
 
-def set_intersection__Set(space, w_left, others_w):
-    if len(others_w) == 0:
-        result = w_left.setdata.copy()
-    else:
-        result = _intersection_multiple(space, w_left, others_w)
-    return w_left._newobj(space, result)
-
 frozenset_intersection__Frozenset = set_intersection__Set
 
 def set_intersection_update__Set(space, w_left, others_w):
-    result = _intersection_multiple(space, w_left, others_w)
-    w_left.setdata = result
+    result = set_intersection__Set(space, w_left, others_w)
+    w_left.strategy = result.strategy
+    w_left.sstorage = result.sstorage
+    return
 
 def inplace_and__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _intersection_dict(space, ld, rd)
-    w_left.setdata = new_ld
+    w_left.intersect_update(w_other)
     return w_left
 
 inplace_and__Set_Frozenset = inplace_and__Set_Set
 
 def set_isdisjoint__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
-    ld, rd = w_left.setdata, w_other.setdata
-    disjoint = _isdisjoint_dict(ld, rd)
-    return space.newbool(disjoint)
+    return space.newbool(w_left.isdisjoint(w_other))
 
 set_isdisjoint__Set_Frozenset = set_isdisjoint__Set_Set
 set_isdisjoint__Frozenset_Frozenset = set_isdisjoint__Set_Set
 set_isdisjoint__Frozenset_Set = set_isdisjoint__Set_Set
 
 def set_isdisjoint__Set_ANY(space, w_left, w_other):
-    ld = w_left.setdata
+    #XXX may be optimized when other strategies are added
     for w_key in space.listview(w_other):
-        if w_key in ld:
+        if w_left.has_key(w_key):
             return space.w_False
     return space.w_True
 
@@ -540,9 +1298,8 @@
 
 def set_symmetric_difference__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    w_result = w_left.symmetric_difference(w_other)
+    return w_result
 
 set_symmetric_difference__Set_Frozenset = set_symmetric_difference__Set_Set
 set_symmetric_difference__Frozenset_Set = set_symmetric_difference__Set_Set
@@ -556,26 +1313,23 @@
 
 
 def set_symmetric_difference__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    w_other_as_set = w_left._newobj(space, w_other)
+    w_result = w_left.symmetric_difference(w_other_as_set)
+    return w_result
 
 frozenset_symmetric_difference__Frozenset_ANY = \
         set_symmetric_difference__Set_ANY
 
 def set_symmetric_difference_update__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    w_left.setdata = new_ld
+    w_left.symmetric_difference_update(w_other)
 
 set_symmetric_difference_update__Set_Frozenset = \
                                     set_symmetric_difference_update__Set_Set
 
 def set_symmetric_difference_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    w_left.setdata = new_ld
+    w_other_as_set = w_left._newobj(space, w_other)
+    w_left.symmetric_difference_update(w_other_as_set)
 
 def inplace_xor__Set_Set(space, w_left, w_other):
     set_symmetric_difference_update__Set_Set(space, w_left, w_other)
@@ -584,34 +1338,33 @@
 inplace_xor__Set_Frozenset = inplace_xor__Set_Set
 
 def or__Set_Set(space, w_left, w_other):
-    ld, rd = w_left.setdata, w_other.setdata
-    result = ld.copy()
-    result.update(rd)
-    return w_left._newobj(space, result)
+    w_copy = w_left.copy_real()
+    w_copy.update(w_other)
+    return w_copy
 
 or__Set_Frozenset = or__Set_Set
 or__Frozenset_Set = or__Set_Set
 or__Frozenset_Frozenset = or__Set_Set
 
 def set_union__Set(space, w_left, others_w):
-    result = w_left.setdata.copy()
+    result = w_left.copy_real()
     for w_other in others_w:
         if isinstance(w_other, W_BaseSetObject):
-            result.update(w_other.setdata)     # optimization only
+            result.update(w_other)     # optimization only
         else:
             for w_key in space.listview(w_other):
-                result[w_key] = None
-    return w_left._newobj(space, result)
+                result.add(w_key)
+    return result
 
 frozenset_union__Frozenset = set_union__Set
 
 def len__Set(space, w_left):
-    return space.newint(len(w_left.setdata))
+    return space.newint(w_left.length())
 
 len__Frozenset = len__Set
 
 def iter__Set(space, w_left):
-    return W_SetIterObject(w_left.setdata)
+    return W_SetIterObject(space, w_left.iter())
 
 iter__Frozenset = iter__Set
 
diff --git a/pypy/objspace/std/settype.py b/pypy/objspace/std/settype.py
--- a/pypy/objspace/std/settype.py
+++ b/pypy/objspace/std/settype.py
@@ -68,7 +68,7 @@
 def descr__new__(space, w_settype, __args__):
     from pypy.objspace.std.setobject import W_SetObject, newset
     w_obj = space.allocate_instance(W_SetObject, w_settype)
-    W_SetObject.__init__(w_obj, space, newset(space))
+    W_SetObject.__init__(w_obj, space)
     return w_obj
 
 set_typedef = StdTypeDef("set",
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -69,6 +69,14 @@
     def str_w(w_self, space):
         return w_self._value
 
+    def listview_str(w_self):
+        return _create_list_from_string(w_self._value)
+
+def _create_list_from_string(value):
+    # need this helper function to allow the jit to look inside and inline
+    # listview_str
+    return [s for s in value]
+
 registerimplementation(W_StringObject)
 
 W_StringObject.EMPTY = W_StringObject('')
diff --git a/pypy/objspace/std/test/test_builtinshortcut.py b/pypy/objspace/std/test/test_builtinshortcut.py
--- a/pypy/objspace/std/test/test_builtinshortcut.py
+++ b/pypy/objspace/std/test/test_builtinshortcut.py
@@ -85,6 +85,20 @@
     def setup_class(cls):
         from pypy import conftest
         cls.space = conftest.gettestobjspace(**WITH_BUILTINSHORTCUT)
+        w_fakeint = cls.space.appexec([], """():
+            class FakeInt(object):
+                def __init__(self, value):
+                    self.value = value
+                def __hash__(self):
+                    return hash(self.value)
+
+                def __eq__(self, other):
+                    if other == self.value:
+                        return True
+                    return False
+            return FakeInt
+            """)
+        cls.w_FakeInt = w_fakeint
 
 class AppTestString(test_stringobject.AppTestStringObject):
     def setup_class(cls):
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
@@ -131,6 +131,45 @@
         assert self.space.eq_w(space.call_function(get, w("33")), w(None))
         assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44))
 
+    def test_fromkeys_fastpath(self):
+        space = self.space
+        w = space.wrap
+
+        w_l = self.space.newlist([w("a"),w("b")])
+        w_l.getitems = None
+        w_d = space.call_method(space.w_dict, "fromkeys", w_l)
+
+        assert space.eq_w(w_d.getitem_str("a"), space.w_None)
+        assert space.eq_w(w_d.getitem_str("b"), space.w_None)
+
+    def test_listview_str_dict(self):
+        w = self.space.wrap
+
+        w_d = self.space.newdict()
+        w_d.initialize_content([(w("a"), w(1)), (w("b"), w(2))])
+
+        assert self.space.listview_str(w_d) == ["a", "b"]
+
+    def test_listview_int_dict(self):
+        w = self.space.wrap
+        w_d = self.space.newdict()
+        w_d.initialize_content([(w(1), w("a")), (w(2), w("b"))])
+
+        assert self.space.listview_int(w_d) == [1, 2]
+
+    def test_keys_on_string_int_dict(self):
+        w = self.space.wrap
+        w_d = self.space.newdict()
+        w_d.initialize_content([(w(1), w("a")), (w(2), w("b"))])
+
+        w_l = self.space.call_method(w_d, "keys")
+        assert sorted(self.space.listview_int(w_l)) == [1,2]
+
+        w_d = self.space.newdict()
+        w_d.initialize_content([(w("a"), w(1)), (w("b"), w(6))])
+
+        w_l = self.space.call_method(w_d, "keys")
+        assert sorted(self.space.listview_str(w_l)) == ["a", "b"]
 
 class AppTest_DictObject:
     def setup_class(cls):
@@ -793,7 +832,9 @@
         return x == y
     eq_w = eq
     def newlist(self, l):
-        return []
+        return l
+    def newlist_str(self, l):
+        return l
     DictObjectCls = W_DictMultiObject
     def type(self, w_obj):
         if isinstance(w_obj, FakeString):
@@ -933,7 +974,7 @@
 
     def test_keys(self):
         self.fill_impl()
-        keys = self.impl.keys()
+        keys = self.impl.w_keys() # wrapped lists = lists in the fake space
         keys.sort()
         assert keys == [self.string, self.string2]
         self.check_not_devolved()
@@ -1011,8 +1052,8 @@
         d.setitem("s", 12)
         d.delitem(F())
 
-        assert "s" not in d.keys()
-        assert F() not in d.keys()
+        assert "s" not in d.w_keys()
+        assert F() not in d.w_keys()
 
 class TestStrDictImplementation(BaseTestRDictImplementation):
     StrategyClass = StringDictStrategy
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -486,6 +486,14 @@
         list.__init__(l, ['a', 'b', 'c'])
         assert l is l0
         assert l == ['a', 'b', 'c']
+        list.__init__(l)
+        assert l == []
+
+    def test_explicit_new_init_more_cases(self):
+        for assignment in [[], (), [3], ["foo"]]:
+            l = [1, 2]
+            l.__init__(assignment)
+            assert l == list(assignment)
 
     def test_extend_list(self):
         l = l0 = [1]
@@ -1173,6 +1181,20 @@
         assert l == []
         assert list(g) == []
 
+    def test_uses_custom_iterator(self):
+        # obscure corner case: space.listview*() must not shortcut subclasses
+        # of dicts, because the OrderedDict in the stdlib relies on this.
+        # we extend the use case to lists and sets, i.e. all types that have
+        # strategies, to avoid surprizes depending on the strategy.
+        for base, arg in [(list, []), (list, [5]), (list, ['x']),
+                          (set, []),  (set,  [5]), (set,  ['x']),
+                          (dict, []), (dict, [(5,6)]), (dict, [('x',7)])]:
+            print base, arg
+            class SubClass(base):
+                def __iter__(self):
+                    return iter("foobar")
+            assert list(SubClass(arg)) == ['f', 'o', 'o', 'b', 'a', 'r']
+
 class AppTestForRangeLists(AppTestW_ListObject):
 
     def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -420,7 +420,7 @@
 
     def test_listview_str(self):
         space = self.space
-        assert space.listview_str(space.wrap("a")) is None
+        assert space.listview_str(space.wrap(1)) == None
         w_l = self.space.newlist([self.space.wrap('a'), self.space.wrap('b')])
         assert space.listview_str(w_l) == ["a", "b"]
 
@@ -463,6 +463,44 @@
         w_res = listobject.list_pop__List_ANY(space, w_l, space.w_None) # does not crash
         assert space.unwrap(w_res) == 3
 
+    def test_create_list_from_set(self):
+        from pypy.objspace.std.setobject import W_SetObject
+        from pypy.objspace.std.setobject import _initialize_set
+
+        space = self.space
+        w = space.wrap
+
+        w_l = W_ListObject(space, [space.wrap(1), space.wrap(2), space.wrap(3)])
+
+        w_set = W_SetObject(self.space)
+        _initialize_set(self.space, w_set, w_l)
+        w_set.iter = None # make sure fast path is used
+
+        w_l2 = W_ListObject(space, [])
+        space.call_method(w_l2, "__init__", w_set)
+
+        w_l2.sort(False)
+        assert space.eq_w(w_l, w_l2)
+
+        w_l = W_ListObject(space, [space.wrap("a"), space.wrap("b"), space.wrap("c")])
+        _initialize_set(self.space, w_set, w_l)
+
+        space.call_method(w_l2, "__init__", w_set)
+
+        w_l2.sort(False)
+        assert space.eq_w(w_l, w_l2)
+
+
+    def test_listview_str_list(self):
+        space = self.space
+        w_l = W_ListObject(space, [space.wrap("a"), space.wrap("b")])
+        assert self.space.listview_str(w_l) == ["a", "b"]
+
+    def test_listview_int_list(self):
+        space = self.space
+        w_l = W_ListObject(space, [space.wrap(1), space.wrap(2), space.wrap(3)])
+        assert self.space.listview_int(w_l) == [1, 2, 3]
+
 
 class TestW_ListStrategiesDisabled:
     def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -8,12 +8,14 @@
 is not too wrong.
 """
 import py.test
-from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
+from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject, IntegerSetStrategy
 from pypy.objspace.std.setobject import _initialize_set
-from pypy.objspace.std.setobject import newset, make_setdata_from_w_iterable
+from pypy.objspace.std.setobject import newset
 from pypy.objspace.std.setobject import and__Set_Set
 from pypy.objspace.std.setobject import set_intersection__Set
 from pypy.objspace.std.setobject import eq__Set_Set
+from pypy.conftest import gettestobjspace
+from pypy.objspace.std.listobject import W_ListObject
 
 letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
@@ -29,12 +31,11 @@
         self.false = self.space.w_False
 
     def test_and(self):
-        s = W_SetObject(self.space, newset(self.space))
+        s = W_SetObject(self.space)
         _initialize_set(self.space, s, self.word)
-        t0 = W_SetObject(self.space, newset(self.space))
+        t0 = W_SetObject(self.space)
         _initialize_set(self.space, t0, self.otherword)
-        t1 = W_FrozensetObject(self.space,
-                make_setdata_from_w_iterable(self.space, self.otherword))
+        t1 = W_FrozensetObject(self.space, self.otherword)
         r0 = and__Set_Set(self.space, s, t0)
         r1 = and__Set_Set(self.space, s, t1)
         assert eq__Set_Set(self.space, r0, r1) == self.true
@@ -42,9 +43,9 @@
         assert eq__Set_Set(self.space, r0, sr) == self.true
 
     def test_compare(self):
-        s = W_SetObject(self.space, newset(self.space))
+        s = W_SetObject(self.space)
         _initialize_set(self.space, s, self.word)
-        t = W_SetObject(self.space, newset(self.space))
+        t = W_SetObject(self.space)
         _initialize_set(self.space, t, self.word)
         assert self.space.eq_w(s,t)
         u = self.space.wrap(set('simsalabim'))
@@ -54,7 +55,247 @@
         s = self.space.newset()
         assert self.space.str_w(self.space.repr(s)) == 'set([])'
 
+    def test_intersection_order(self):
+        # theses tests make sure that intersection is done in the correct order
+        # (smallest first)
+        space = self.space
+        a = W_SetObject(self.space)
+        _initialize_set(self.space, a, self.space.wrap("abcdefg"))
+        a.intersect = None
+
+        b = W_SetObject(self.space)
+        _initialize_set(self.space, b, self.space.wrap("abc"))
+
+        result = set_intersection__Set(space, a, [b])
+        assert space.is_true(self.space.eq(result, W_SetObject(space, self.space.wrap("abc"))))
+
+        c = W_SetObject(self.space)
+        _initialize_set(self.space, c, self.space.wrap("e"))
+
+        d = W_SetObject(self.space)
+        _initialize_set(self.space, d, self.space.wrap("ab"))
+
+        # if ordering works correct we should start with set e
+        a.get_storage_copy = None
+        b.get_storage_copy = None
+        d.get_storage_copy = None
+
+        result = set_intersection__Set(space, a, [d,c,b])
+        assert space.is_true(self.space.eq(result, W_SetObject(space, self.space.wrap(""))))
+
+    def test_create_set_from_list(self):
+        from pypy.objspace.std.setobject import ObjectSetStrategy, StringSetStrategy
+        from pypy.objspace.std.floatobject import W_FloatObject
+        from pypy.objspace.std.model import W_Object
+
+        w = self.space.wrap
+        intstr = self.space.fromcache(IntegerSetStrategy)
+        tmp_func = intstr.get_storage_from_list
+        # test if get_storage_from_list is no longer used
+        intstr.get_storage_from_list = None
+
+        w_list = W_ListObject(self.space, [w(1), w(2), w(3)])
+        w_set = W_SetObject(self.space)
+        _initialize_set(self.space, w_set, w_list)
+        assert w_set.strategy is intstr
+        assert intstr.unerase(w_set.sstorage) == {1:None, 2:None, 3:None}
+
+        w_list = W_ListObject(self.space, [w("1"), w("2"), w("3")])
+        w_set = W_SetObject(self.space)
+        _initialize_set(self.space, w_set, w_list)
+        assert w_set.strategy is self.space.fromcache(StringSetStrategy)
+        assert w_set.strategy.unerase(w_set.sstorage) == {"1":None, "2":None, "3":None}
+
+        w_list = W_ListObject(self.space, [w("1"), w(2), w("3")])
+        w_set = W_SetObject(self.space)
+        _initialize_set(self.space, w_set, w_list)
+        assert w_set.strategy is self.space.fromcache(ObjectSetStrategy)
+        for item in w_set.strategy.unerase(w_set.sstorage):
+            assert isinstance(item, W_Object)
+
+        w_list = W_ListObject(self.space, [w(1.0), w(2.0), w(3.0)])
+        w_set = W_SetObject(self.space)
+        _initialize_set(self.space, w_set, w_list)
+        assert w_set.strategy is self.space.fromcache(ObjectSetStrategy)
+        for item in w_set.strategy.unerase(w_set.sstorage):
+            assert isinstance(item, W_FloatObject)
+
+        # changed cached object, need to change it back for other tests to pass
+        intstr.get_storage_from_list = tmp_func
+
+    def test_listview_str_int_on_set(self):
+        w = self.space.wrap
+
+        w_a = W_SetObject(self.space)
+        _initialize_set(self.space, w_a, w("abcdefg"))
+        assert sorted(self.space.listview_str(w_a)) == list("abcdefg")
+        assert self.space.listview_int(w_a) is None
+
+        w_b = W_SetObject(self.space)
+        _initialize_set(self.space, w_b, self.space.newlist([w(1),w(2),w(3),w(4),w(5)]))
+        assert sorted(self.space.listview_int(w_b)) == [1,2,3,4,5]
+        assert self.space.listview_str(w_b) is None
+
 class AppTestAppSetTest:
+
+    def setup_class(self):
+        self.space = gettestobjspace()
+        w_fakeint = self.space.appexec([], """():
+            class FakeInt(object):
+                def __init__(self, value):
+                    self.value = value
+                def __hash__(self):
+                    return hash(self.value)
+
+                def __eq__(self, other):
+                    if other == self.value:
+                        return True
+                    return False
+            return FakeInt
+            """)
+        self.w_FakeInt = w_fakeint
+
+    def test_fakeint(self):
+        f1 = self.FakeInt(4)
+        assert f1 == 4
+        assert hash(f1) == hash(4)
+
+    def test_simple(self):
+        a = set([1,2,3])
+        b = set()
+        b.add(4)
+        c = a.union(b)
+        assert c == set([1,2,3,4])
+
+    def test_generator(self):
+        def foo():
+            for i in [1,2,3,4,5]:
+                yield i
+        b = set(foo())
+        assert b == set([1,2,3,4,5])
+
+        a = set(x for x in [1,2,3])
+        assert a == set([1,2,3])
+
+    def test_generator2(self):
+        def foo():
+            for i in [1,2,3]:
+                yield i
+        class A(set):
+            pass
+        a = A([1,2,3,4,5])
+        b = a.difference(foo())
+        assert b == set([4,5])
+
+    def test_or(self):
+        a = set([0,1,2])
+        b = a | set([1,2,3])
+        assert b == set([0,1,2,3])
+
+        # test inplace or
+        a |= set([1,2,3])
+        assert a == b
+
+    def test_clear(self):
+        a = set([1,2,3])
+        a.clear()
+        assert a == set()
+
+    def test_sub(self):
+        a = set([1,2,3,4,5])
+        b = set([2,3,4])
+        a - b == [1,5]
+        a.__sub__(b) == [1,5]
+
+        #inplace sub
+        a = set([1,2,3,4])
+        b = set([1,4])
+        a -= b
+        assert a == set([2,3])
+
+    def test_issubset(self):
+        a = set([1,2,3,4])
+        b = set([2,3])
+        assert b.issubset(a)
+        c = [1,2,3,4]
+        assert b.issubset(c)
+
+        a = set([1,2,3,4])
+        b = set(['1','2'])
+        assert not b.issubset(a)
+
+    def test_issuperset(self):
+        a = set([1,2,3,4])
+        b = set([2,3])
+        assert a.issuperset(b)
+        c = [2,3]
+        assert a.issuperset(c)
+
+        c = [1,1,1,1,1]
+        assert a.issuperset(c)
+        assert set([1,1,1,1,1]).issubset(a)
+
+        a = set([1,2,3])
+        assert a.issuperset(a)
+        assert not a.issuperset(set([1,2,3,4,5]))
+
+    def test_inplace_and(test):
+        a = set([1,2,3,4])
+        b = set([0,2,3,5,6])
+        a &= b
+        assert a == set([2,3])
+
+    def test_discard_remove(self):
+        a = set([1,2,3,4,5])
+        a.remove(1)
+        assert a == set([2,3,4,5])
+        a.discard(2)
+        assert a == set([3,4,5])
+
+        raises(KeyError, "a.remove(6)")
+
+    def test_pop(self):
+        b = set()
+        raises(KeyError, "b.pop()")
+
+        a = set([1,2,3,4,5])
+        for i in xrange(5):
+            a.pop()
+        assert a == set()
+        raises(KeyError, "a.pop()")
+
+    def test_symmetric_difference(self):
+        a = set([1,2,3])
+        b = set([3,4,5])
+        c = a.symmetric_difference(b)
+        assert c == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = [3,4,5]
+        c = a.symmetric_difference(b)
+        assert c == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = set('abc')
+        c = a.symmetric_difference(b)
+        assert c == set([1,2,3,'a','b','c'])
+
+    def test_symmetric_difference_update(self):
+        a = set([1,2,3])
+        b = set([3,4,5])
+        a.symmetric_difference_update(b)
+        assert a == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = [3,4,5]
+        a.symmetric_difference_update(b)
+        assert a == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = set([3,4,5])
+        a ^= b
+        assert a == set([1,2,4,5])
+
     def test_subtype(self):
         class subset(set):pass
         a = subset()
@@ -131,6 +372,8 @@
         assert (set('abc') != set('abcd'))
         assert (frozenset('abc') != frozenset('abcd'))
         assert (frozenset('abc') != set('abcd'))
+        assert set() != set('abc')
+        assert set('abc') != set('abd')
 
     def test_libpython_equality(self):
         for thetype in [frozenset, set]:
@@ -178,6 +421,9 @@
         s1 = set('abc')
         s1.update('d', 'ef', frozenset('g'))
         assert s1 == set('abcdefg')
+        s1 = set()
+        s1.update(set('abcd'))
+        assert s1 == set('abcd')
 
     def test_recursive_repr(self):
         class A(object):
@@ -330,6 +576,7 @@
         assert not set([1,2,5]).isdisjoint(frozenset([4,5,6]))
         assert not set([1,2,5]).isdisjoint([4,5,6])
         assert not set([1,2,5]).isdisjoint((4,5,6))
+        assert set([1,2,3]).isdisjoint(set([3.5,4.0]))
 
     def test_intersection(self):
         assert set([1,2,3]).intersection(set([2,3,4])) == set([2,3])
@@ -347,6 +594,35 @@
         assert s.intersection() == s
         assert s.intersection() is not s
 
+    def test_intersection_swap(self):
+        s1 = s3 = set([1,2,3,4,5])
+        s2 = set([2,3,6,7])
+        s1 &= s2
+        assert s1 == set([2,3])
+        assert s3 == set([2,3])
+
+    def test_intersection_generator(self):
+        def foo():
+            for i in range(5):
+                yield i
+
+        s1 = s2 = set([1,2,3,4,5,6])
+        assert s1.intersection(foo()) == set([1,2,3,4])
+        s1.intersection_update(foo())
+        assert s1 == set([1,2,3,4])
+        assert s2 == set([1,2,3,4])
+
+    def test_intersection_string(self):
+        s = set([1,2,3])
+        o = 'abc'
+        assert s.intersection(o) == set()
+
+    def test_intersection_float(self):
+        a = set([1,2,3])
+        b = set([3.0,4.0,5.0])
+        c = a.intersection(b)
+        assert c == set([3.0])
+
     def test_difference(self):
         assert set([1,2,3]).difference(set([2,3,4])) == set([1])
         assert set([1,2,3]).difference(frozenset([2,3,4])) == set([1])
@@ -361,6 +637,9 @@
         s = set([1,2,3])
         assert s.difference() == s
         assert s.difference() is not s
+        assert set([1,2,3]).difference(set([2,3,4,'5'])) == set([1])
+        assert set([1,2,3,'5']).difference(set([2,3,4])) == set([1,'5'])
+        assert set().difference(set([1,2,3])) == set()
 
     def test_intersection_update(self):
         s = set([1,2,3,4,7])
@@ -381,3 +660,250 @@
         assert s == set([2,3])
         s.difference_update(s)
         assert s == set([])
+
+    def test_empty_empty(self):
+        assert set() == set([])
+
+    def test_empty_difference(self):
+        e = set()
+        x = set([1,2,3])
+        assert e.difference(x) == set()
+        assert x.difference(e) == x
+
+        e.difference_update(x)
+        assert e == set()
+        x.difference_update(e)
+        assert x == set([1,2,3])
+
+        assert e.symmetric_difference(x) == x
+        assert x.symmetric_difference(e) == x
+
+        e.symmetric_difference_update(e)
+        assert e == e
+        e.symmetric_difference_update(x)
+        assert e == x
+
+        x.symmetric_difference_update(set())
+        assert x == set([1,2,3])
+
+    def test_fastpath_with_strategies(self):
+        a = set([1,2,3])
+        b = set(["a","b","c"])
+        assert a.difference(b) == a
+        assert b.difference(a) == b
+
+        a = set([1,2,3])
+        b = set(["a","b","c"])
+        assert a.intersection(b) == set()
+        assert b.intersection(a) == set()
+
+        a = set([1,2,3])
+        b = set(["a","b","c"])
+        assert not a.issubset(b)
+        assert not b.issubset(a)
+
+        a = set([1,2,3])
+        b = set(["a","b","c"])
+        assert a.isdisjoint(b)
+        assert b.isdisjoint(a)
+
+    def test_empty_intersect(self):
+        e = set()
+        x = set([1,2,3])
+        assert e.intersection(x) == e
+        assert x.intersection(e) == e
+        assert e & x == e
+        assert x & e == e
+
+        e.intersection_update(x)
+        assert e == set()
+        e &= x
+        assert e == set()
+        x.intersection_update(e)
+        assert x == set()
+
+    def test_empty_issuper(self):
+        e = set()
+        x = set([1,2,3])
+        assert e.issuperset(e) == True
+        assert e.issuperset(x) == False
+        assert x.issuperset(e) == True
+
+        assert e.issuperset(set())
+        assert e.issuperset([])
+
+    def test_empty_issubset(self):
+        e = set()
+        x = set([1,2,3])
+        assert e.issubset(e) == True
+        assert e.issubset(x) == True
+        assert x.issubset(e) == False
+        assert e.issubset([])
+
+    def test_empty_isdisjoint(self):
+        e = set()
+        x = set([1,2,3])
+        assert e.isdisjoint(e) == True
+        assert e.isdisjoint(x) == True
+        assert x.isdisjoint(e) == True
+
+    def test_empty_unhashable(self):
+        s = set()
+        raises(TypeError, s.difference, [[]])
+        raises(TypeError, s.difference_update, [[]])
+        raises(TypeError, s.intersection, [[]])
+        raises(TypeError, s.intersection_update, [[]])
+        raises(TypeError, s.symmetric_difference, [[]])
+        raises(TypeError, s.symmetric_difference_update, [[]])
+        raises(TypeError, s.update, [[]])
+
+    def test_super_with_generator(self):
+        def foo():
+            for i in [1,2,3]:
+                yield i
+        set([1,2,3,4,5]).issuperset(foo())
+
+    def test_isdisjoint_with_generator(self):
+        def foo():
+            for i in [1,2,3]:
+                yield i
+        set([1,2,3,4,5]).isdisjoint(foo())
+
+    def test_fakeint_and_equals(self):
+        s1 = set([1,2,3,4])
+        s2 = set([1,2,self.FakeInt(3), 4])
+        assert s1 == s2
+
+    def test_fakeint_and_discard(self):
+        # test with object strategy
+        s = set([1, 2, 'three', 'four'])
+        s.discard(self.FakeInt(2))
+        assert s == set([1, 'three', 'four'])
+
+        s.remove(self.FakeInt(1))
+        assert s == set(['three', 'four'])
+        raises(KeyError, s.remove, self.FakeInt(16))
+
+        # test with int strategy
+        s = set([1,2,3,4])
+        s.discard(self.FakeInt(4))
+        assert s == set([1,2,3])
+        s.remove(self.FakeInt(3))
+        assert s == set([1,2])
+        raises(KeyError, s.remove, self.FakeInt(16))
+
+    def test_fakeobject_and_has_key(self):
+        s = set([1,2,3,4,5])
+        assert 5 in s
+        assert self.FakeInt(5) in s
+
+    def test_fakeobject_and_pop(self):
+        s = set([1,2,3,self.FakeInt(4),5])
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s == set([])
+
+    def test_fakeobject_and_difference(self):
+        s = set([1,2,'3',4])
+        s.difference_update([self.FakeInt(1), self.FakeInt(2)])
+        assert s == set(['3',4])
+
+        s = set([1,2,3,4])
+        s.difference_update([self.FakeInt(1), self.FakeInt(2)])
+        assert s == set([3,4])
+
+    def test_frozenset_behavior(self):
+        s = set([1,2,3,frozenset([4])])
+        raises(TypeError, s.difference_update, [1,2,3,set([4])])
+
+        s = set([1,2,3,frozenset([4])])
+        s.discard(set([4]))
+        assert s == set([1,2,3])
+
+    def test_discard_unhashable(self):
+        s = set([1,2,3,4])
+        raises(TypeError, s.discard, [1])
+
+    def test_discard_evil_compare(self):
+        class Evil(object):
+            def __init__(self, value):
+                self.value = value
+            def __hash__(self):
+                return hash(self.value)
+            def __eq__(self, other):
+                if isinstance(other, frozenset):
+                    raise TypeError
+                if other == self.value:
+                    return True
+                return False
+        s = set([1,2, Evil(frozenset([1]))])
+        raises(TypeError, s.discard, set([1]))
+
+    def test_create_set_from_set(self):
+        # no sharing
+        x = set([1,2,3])
+        y = set(x)
+        a = x.pop()
+        assert y == set([1,2,3])
+        assert len(x) == 2
+        assert x.union(set([a])) == y
+
+    def test_never_change_frozenset(self):
+        a = frozenset([1,2])
+        b = a.copy()
+        assert a is b
+
+        a = frozenset([1,2])
+        b = a.union(set([3,4]))
+        assert b == set([1,2,3,4])
+        assert a == set([1,2])
+
+        a = frozenset()
+        b = a.union(set([3,4]))
+        assert b == set([3,4])
+        assert a == set()
+
+        a = frozenset([1,2])#multiple
+        b = a.union(set([3,4]),[5,6])
+        assert b == set([1,2,3,4,5,6])
+        assert a == set([1,2])
+
+        a = frozenset([1,2,3])
+        b = a.difference(set([3,4,5]))
+        assert b == set([1,2])
+        assert a == set([1,2,3])
+
+        a = frozenset([1,2,3])#multiple
+        b = a.difference(set([3]), [2])
+        assert b == set([1])
+        assert a == set([1,2,3])
+
+        a = frozenset([1,2,3])
+        b = a.symmetric_difference(set([3,4,5]))
+        assert b == set([1,2,4,5])
+        assert a == set([1,2,3])
+
+        a = frozenset([1,2,3])
+        b = a.intersection(set([3,4,5]))
+        assert b == set([3])
+        assert a == set([1,2,3])
+
+        a = frozenset([1,2,3])#multiple
+        b = a.intersection(set([2,3,4]), [2])
+        assert b == set([2])
+        assert a == set([1,2,3])
+
+        raises(AttributeError, "frozenset().update()")
+        raises(AttributeError, "frozenset().difference_update()")
+        raises(AttributeError, "frozenset().symmetric_difference_update()")
+        raises(AttributeError, "frozenset().intersection_update()")
+
+    def test_intersection_obj(self):
+        class Obj:
+            def __getitem__(self, i):
+                return [5, 3, 4][i]
+        s = set([10,3,2]).intersection(Obj())
+        assert list(s) == [3]
diff --git a/pypy/objspace/std/test/test_setstrategies.py b/pypy/objspace/std/test/test_setstrategies.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_setstrategies.py
@@ -0,0 +1,107 @@
+from pypy.objspace.std.setobject import W_SetObject
+from pypy.objspace.std.setobject import IntegerSetStrategy, ObjectSetStrategy, EmptySetStrategy
+from pypy.objspace.std.listobject import W_ListObject
+
+class TestW_SetStrategies:
+
+    def wrapped(self, l):
+        return W_ListObject(self.space, [self.space.wrap(x) for x in l])
+
+    def test_from_list(self):
+        s = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        assert s.strategy is self.space.fromcache(IntegerSetStrategy)
+
+        s = W_SetObject(self.space, self.wrapped([1,"two",3,"four",5]))
+        assert s.strategy is self.space.fromcache(ObjectSetStrategy)
+
+        s = W_SetObject(self.space)
+        assert s.strategy is self.space.fromcache(EmptySetStrategy)
+
+        s = W_SetObject(self.space, self.wrapped([]))
+        assert s.strategy is self.space.fromcache(EmptySetStrategy)
+
+    def test_switch_to_object(self):
+        s = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s.add(self.space.wrap("six"))
+        assert s.strategy is self.space.fromcache(ObjectSetStrategy)
+
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s2 = W_SetObject(self.space, self.wrapped(["six", "seven"]))
+        s1.update(s2)
+        assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+    def test_symmetric_difference(self):
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s2 = W_SetObject(self.space, self.wrapped(["six", "seven"]))
+        s1.symmetric_difference_update(s2)
+        assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+    def test_intersection(self):
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s2 = W_SetObject(self.space, self.wrapped([4,5, "six", "seven"]))
+        s3 = s1.intersect(s2)
+        skip("for now intersection with ObjectStrategy always results in another ObjectStrategy")
+        assert s3.strategy is self.space.fromcache(IntegerSetStrategy)
+
+    def test_clear(self):
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s1.clear()
+        assert s1.strategy is self.space.fromcache(EmptySetStrategy)
+
+    def test_remove(self):
+        from pypy.objspace.std.setobject import set_remove__Set_ANY
+        s1 = W_SetObject(self.space, self.wrapped([1]))
+        set_remove__Set_ANY(self.space, s1, self.space.wrap(1))
+        assert s1.strategy is self.space.fromcache(EmptySetStrategy)
+
+    def test_union(self):
+        from pypy.objspace.std.setobject import set_union__Set
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        s2 = W_SetObject(self.space, self.wrapped([4,5,6,7]))
+        s3 = W_SetObject(self.space, self.wrapped([4,'5','6',7]))
+        s4 = set_union__Set(self.space, s1, [s2])
+        s5 = set_union__Set(self.space, s1, [s3])
+        assert s4.strategy is self.space.fromcache(IntegerSetStrategy)
+        assert s5.strategy is self.space.fromcache(ObjectSetStrategy)
+
+    def test_discard(self):
+        class FakeInt(object):
+            def __init__(self, value):
+                self.value = value
+            def __hash__(self):
+                return hash(self.value)
+            def __eq__(self, other):
+                if other == self.value:
+                    return True
+                return False
+
+        from pypy.objspace.std.setobject import set_discard__Set_ANY
+
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        set_discard__Set_ANY(self.space, s1, self.space.wrap("five"))
+        skip("currently not supported")
+        assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
+
+        set_discard__Set_ANY(self.space, s1, self.space.wrap(FakeInt(5)))
+        assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+    def test_has_key(self):
+        class FakeInt(object):
+            def __init__(self, value):
+                self.value = value
+            def __hash__(self):
+                return hash(self.value)
+            def __eq__(self, other):
+                if other == self.value:
+                    return True
+                return False
+
+        from pypy.objspace.std.setobject import set_discard__Set_ANY
+
+        s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+        assert not s1.has_key(self.space.wrap("five"))
+        skip("currently not supported")
+        assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
+
+        assert s1.has_key(self.space.wrap(FakeInt(2)))
+        assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -85,6 +85,10 @@
         w_slice = space.newslice(w(1), w_None, w(2))
         assert self.space.eq_w(space.getitem(w_str, w_slice), w('el'))
 
+    def test_listview_str(self):
+        w_str = self.space.wrap('abcd')
+        assert self.space.listview_str(w_str) == list("abcd")
+
 class AppTestStringObject:
 
     def test_format_wrongchar(self):
diff --git a/pypy/translator/c/gcc/test/test_asmgcroot.py b/pypy/translator/c/gcc/test/test_asmgcroot.py
--- a/pypy/translator/c/gcc/test/test_asmgcroot.py
+++ b/pypy/translator/c/gcc/test/test_asmgcroot.py
@@ -6,10 +6,18 @@
 from pypy.annotation.listdef import s_list_of_strings
 from pypy import conftest
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.translator.platform import platform as compiler
+from pypy.rlib.rarithmetic import is_emulated_long
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.entrypoint import entrypoint, secondary_entrypoints
 from pypy.rpython.lltypesystem.lloperation import llop
 
+_MSVC = compiler.name == "msvc"
+_MINGW = compiler.name == "mingw32"
+_WIN32 = _MSVC or _MINGW
+_WIN64 = _WIN32 and is_emulated_long
+# XXX get rid of 'is_emulated_long' and have a real config here.
+
 class AbstractTestAsmGCRoot:
     # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
     # instructions:
@@ -17,6 +25,8 @@
 
     @classmethod
     def make_config(cls):
+        if _MSVC and _WIN64:
+            py.test.skip("all asmgcroot tests disabled for MSVC X64")
         from pypy.config.pypyoption import get_pypy_config
         config = get_pypy_config(translating=True)
         config.translation.gc = cls.gcpolicy


More information about the pypy-commit mailing list