[pypy-commit] pypy jit-targets: hg merge default

hakanardo noreply at buildbot.pypy.org
Sun Dec 4 20:10:03 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r50141:a18379234939
Date: 2011-12-04 20:08 +0100
http://bitbucket.org/pypy/pypy/changeset/a18379234939/

Log:	hg merge default

diff --git a/lib_pypy/_sha.py b/lib_pypy/_sha.py
--- a/lib_pypy/_sha.py
+++ b/lib_pypy/_sha.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# -*- coding: iso-8859-1
+# -*- coding: iso-8859-1 -*-
 
 # Note that PyPy contains also a built-in module 'sha' which will hide
 # this one if compiled in.
diff --git a/lib_pypy/itertools.py b/lib_pypy/itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/itertools.py
@@ -25,7 +25,7 @@
 
 __all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
            'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
-           'takewhile', 'tee']
+           'takewhile', 'tee', 'compress', 'product']
 
 try: from __pypy__ import builtinify
 except ImportError: builtinify = lambda f: f
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -252,7 +252,26 @@
     # unsignedness is considered a rare and contagious disease
 
     def union((int1, int2)):
-        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        if int1.unsigned == int2.unsigned:
+            knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        else:
+            t1 = int1.knowntype
+            if t1 is bool:
+                t1 = int
+            t2 = int2.knowntype
+            if t2 is bool:
+                t2 = int
+
+            if t2 is int:
+                if int2.nonneg == False:
+                    raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1
+                knowntype = t1
+            elif t1 is int:
+                if int1.nonneg == False:
+                    raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2
+                knowntype = t2
+            else:
+                raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2)
         return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
                            knowntype=knowntype)
 
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -591,13 +591,11 @@
     immutable = True
     def __init__(self, method):
         self.method = method
-        
-NUMBER = object()
+
 annotation_to_ll_map = [
     (SomeSingleFloat(), lltype.SingleFloat),
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
     (s_Bool, lltype.Bool),
-    (SomeInteger(knowntype=r_ulonglong), NUMBER),    
     (SomeFloat(), lltype.Float),
     (SomeLongFloat(), lltype.LongFloat),
     (SomeChar(), lltype.Char),
@@ -623,10 +621,11 @@
             return lltype.Ptr(p.PARENTTYPE)
     if isinstance(s_val, SomePtr):
         return s_val.ll_ptrtype
+    if type(s_val) is SomeInteger:
+        return lltype.build_number(None, s_val.knowntype)
+
     for witness, T in annotation_to_ll_map:
         if witness.contains(s_val):
-            if T is NUMBER:
-                return lltype.build_number(None, s_val.knowntype)
             return T
     if info is None:
         info = ''
@@ -635,7 +634,7 @@
     raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
         info, s_val))
 
-ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map if ll is not NUMBER])
+ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map])
 
 def lltype_to_annotation(T):
     try:
diff --git a/pypy/annotation/specialize.py b/pypy/annotation/specialize.py
--- a/pypy/annotation/specialize.py
+++ b/pypy/annotation/specialize.py
@@ -36,9 +36,7 @@
             newtup = SpaceOperation('newtuple', starargs, argscopy[-1])
             newstartblock.operations.append(newtup)
             newstartblock.closeblock(Link(argscopy, graph.startblock))
-            graph.startblock.isstartblock = False
             graph.startblock = newstartblock
-            newstartblock.isstartblock = True
             argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
             graph.signature = Signature(argnames)
             # note that we can mostly ignore defaults: if nb_extra_args > 0, 
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -856,6 +856,46 @@
         py.test.raises(Exception, a.build_types, f, [])
         # if you want to get a r_uint, you have to be explicit about it
 
+    def test_add_different_ints(self):
+        def f(a, b):
+            return a + b
+        a = self.RPythonAnnotator()
+        py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+    def test_merge_different_ints(self):
+        def f(a, b):
+            if a:
+                c = a
+            else:
+                c = b
+            return c
+        a = self.RPythonAnnotator()
+        py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+    def test_merge_ruint_zero(self):
+        def f(a):
+            if a:
+                c = a
+            else:
+                c = 0
+            return c
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [r_uint])
+        assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+    def test_merge_ruint_nonneg_signed(self):
+        def f(a, b):
+            if a:
+                c = a
+            else:
+                assert b >= 0
+                c = b
+            return c
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [r_uint, int])
+        assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+
     def test_prebuilt_long_that_is_not_too_long(self):
         small_constant = 12L
         def f():
@@ -3029,7 +3069,7 @@
             if g(x, y):
                 g(x, r_uint(y))
         a = self.RPythonAnnotator()
-        a.build_types(f, [int, int])
+        py.test.raises(Exception, a.build_types, f, [int, int])
 
     def test_compare_with_zero(self):
         def g():
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -69,8 +69,8 @@
                      "statistics": [("translation.gctransformer", "framework")],
                      "generation": [("translation.gctransformer", "framework")],
                      "hybrid": [("translation.gctransformer", "framework")],
-                     "boehm": [("translation.gctransformer", "boehm"),
-                               ("translation.continuation", False)],  # breaks
+                     "boehm": [("translation.continuation", False),  # breaks
+                               ("translation.gctransformer", "boehm")],
                      "markcompact": [("translation.gctransformer", "framework")],
                      "minimark": [("translation.gctransformer", "framework")],
                      },
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -304,5 +304,14 @@
   never a dictionary as it sometimes is in CPython. Assigning to
   ``__builtins__`` has no effect.
 
+* directly calling the internal magic methods of a few built-in types
+  with invalid arguments may have a slightly different result.  For
+  example, ``[].__add__(None)`` and ``(2).__add__(None)`` both return
+  ``NotImplemented`` on PyPy; on CPython, only the later does, and the
+  former raises ``TypeError``.  (Of course, ``[]+None`` and ``2+None``
+  both raise ``TypeError`` everywhere.)  This difference is an
+  implementation detail that shows up because of internal C-level slots
+  that PyPy does not have.
+
 
 .. include:: _ref.txt
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -15,7 +15,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 1.6`_: the latest official release
+* `Release 1.7`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -75,7 +75,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 1.6`: http://pypy.org/download.html
+.. _`Release 1.7`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
@@ -120,9 +120,9 @@
 Windows, on top of .NET, and on top of Java.
 To dig into PyPy it is recommended to try out the current
 Mercurial default branch, which is always working or mostly working,
-instead of the latest release, which is `1.6`__.
+instead of the latest release, which is `1.7`__.
 
-.. __: release-1.6.0.html
+.. __: release-1.7.0.html
 
 PyPy is mainly developed on Linux and Mac OS X.  Windows is supported,
 but platform-specific bugs tend to take longer before we notice and fix
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -10,7 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated, instantiate
 from pypy.rlib.jit import hint
 from pypy.rlib.debug import make_sure_not_resized, check_nonneg
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rlib import jit
 from pypy.tool import stdlib_opcode
 from pypy.tool.stdlib_opcode import host_bytecode_spec
@@ -167,7 +167,7 @@
                 # Execution starts just after the last_instr.  Initially,
                 # last_instr is -1.  After a generator suspends it points to
                 # the YIELD_VALUE instruction.
-                next_instr = self.last_instr + 1
+                next_instr = r_uint(self.last_instr + 1)
                 if next_instr != 0:
                     self.pushvalue(w_inputvalue)
             #
@@ -691,6 +691,7 @@
     handlerposition = space.int_w(w_handlerposition)
     valuestackdepth = space.int_w(w_valuestackdepth)
     assert valuestackdepth >= 0
+    assert handlerposition >= 0
     blk = instantiate(get_block_class(opname))
     blk.handlerposition = handlerposition
     blk.valuestackdepth = valuestackdepth
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -837,6 +837,7 @@
         raise Yield
 
     def jump_absolute(self, jumpto, next_instr, ec):
+        check_nonneg(jumpto)
         return jumpto
 
     def JUMP_FORWARD(self, jumpby, next_instr):
@@ -1278,7 +1279,7 @@
 
     def handle(self, frame, unroller):
         next_instr = self.really_handle(frame, unroller)   # JIT hack
-        return next_instr
+        return r_uint(next_instr)
 
     def really_handle(self, frame, unroller):
         """ Purely abstract method
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -21,7 +21,7 @@
 from pypy.jit.backend.llgraph import symbolic
 from pypy.jit.codewriter import longlong
 
-from pypy.rlib import libffi
+from pypy.rlib import libffi, clibffi
 from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -1464,6 +1464,10 @@
     res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
     return res
 
+def do_getinteriorfield_raw_float(array, index, width, ofs):
+    res = _getinteriorfield_raw(libffi.types.double, array, index, width, ofs)
+    return res
+
 def _getfield_raw(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1542,12 +1546,17 @@
 do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
 do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
 
-def new_setinteriorfield_raw(ffitype):
+def new_setinteriorfield_raw(cast_func, ffitype):
     def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
         addr = rffi.cast(rffi.VOIDP, array)
+        for TYPE, ffitype2 in clibffi.ffitype_map:
+            if ffitype2 is ffitype:
+                newvalue = cast_func(TYPE, newvalue)
+                break
         return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
     return do_setinteriorfield_raw
-do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(cast_from_int, libffi.types.slong)
+do_setinteriorfield_raw_float = new_setinteriorfield_raw(cast_from_floatstorage, libffi.types.double)
 
 def do_setfield_raw_int(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/jit/backend/llsupport/asmmemmgr.py b/pypy/jit/backend/llsupport/asmmemmgr.py
--- a/pypy/jit/backend/llsupport/asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/asmmemmgr.py
@@ -37,25 +37,25 @@
             self._add_free_block(smaller_stop, stop)
             stop = smaller_stop
             result = (start, stop)
-        self.total_mallocs += stop - start
+        self.total_mallocs += r_uint(stop - start)
         return result   # pair (start, stop)
 
     def free(self, start, stop):
         """Free a block (start, stop) returned by a previous malloc()."""
-        self.total_mallocs -= (stop - start)
+        self.total_mallocs -= r_uint(stop - start)
         self._add_free_block(start, stop)
 
     def open_malloc(self, minsize):
         """Allocate at least minsize bytes.  Returns (start, stop)."""
         result = self._allocate_block(minsize)
         (start, stop) = result
-        self.total_mallocs += stop - start
+        self.total_mallocs += r_uint(stop - start)
         return result
 
     def open_free(self, middle, stop):
         """Used for freeing the end of an open-allocated block of memory."""
         if stop - middle >= self.min_fragment:
-            self.total_mallocs -= (stop - middle)
+            self.total_mallocs -= r_uint(stop - middle)
             self._add_free_block(middle, stop)
             return True
         else:
@@ -77,7 +77,7 @@
                 # Hack to make sure that mcs are not within 32-bits of one
                 # another for testing purposes
                 rmmap.hint.pos += 0x80000000 - size
-        self.total_memory_allocated += size
+        self.total_memory_allocated += r_uint(size)
         data = rffi.cast(lltype.Signed, data)
         return self._add_free_block(data, data + size)
 
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -648,14 +648,10 @@
         # make a malloc function, with two arguments
         def malloc_basic(size, tid):
             type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
-            has_finalizer = bool(tid & (1<<llgroup.HALFSHIFT))
-            has_light_finalizer = bool(tid & (1<<(llgroup.HALFSHIFT + 1)))
             check_typeid(type_id)
             res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
                                                   type_id, size,
-                                                  has_finalizer,
-                                                  has_light_finalizer,
-                                                  False)
+                                                  False, False, False)
             # In case the operation above failed, we are returning NULL
             # from this function to assembler.  There is also an RPython
             # exception set, typically MemoryError; but it's easier and
@@ -749,11 +745,8 @@
     def init_size_descr(self, S, descr):
         type_id = self.layoutbuilder.get_type_id(S)
         assert not self.layoutbuilder.is_weakref_type(S)
-        has_finalizer = bool(self.layoutbuilder.has_finalizer(S))
-        has_light_finalizer = bool(self.layoutbuilder.has_light_finalizer(S))
-        flags = (int(has_finalizer) << llgroup.HALFSHIFT |
-                 int(has_light_finalizer) << (llgroup.HALFSHIFT + 1))
-        descr.tid = llop.combine_ushort(lltype.Signed, type_id, flags)
+        assert not self.layoutbuilder.has_finalizer(S)
+        descr.tid = llop.combine_ushort(lltype.Signed, type_id, 0)
 
     def init_array_descr(self, A, descr):
         type_id = self.layoutbuilder.get_type_id(A)
diff --git a/pypy/jit/backend/llsupport/test/test_regalloc.py b/pypy/jit/backend/llsupport/test/test_regalloc.py
--- a/pypy/jit/backend/llsupport/test/test_regalloc.py
+++ b/pypy/jit/backend/llsupport/test/test_regalloc.py
@@ -2,6 +2,8 @@
 from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxFloat, INT, FLOAT
 from pypy.jit.backend.llsupport.regalloc import FrameManager
 from pypy.jit.backend.llsupport.regalloc import RegisterManager as BaseRegMan
+from pypy.jit.tool.oparser import parse
+from pypy.jit.backend.detect_cpu import getcpuclass
 
 def newboxes(*values):
     return [BoxInt(v) for v in values]
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -168,26 +168,22 @@
         operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
                                                        allgcrefs)
         # compute longevity of variables
-        longevity = self._compute_vars_longevity(inputargs, operations)
+        longevity, useful = self._compute_vars_longevity(inputargs, operations)
         self.longevity = longevity
         self.rm = gpr_reg_mgr_cls(longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)
         self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm,
                                    assembler = self.assembler)
-        return operations
+        return operations, useful
 
     def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
-        operations = self._prepare(inputargs, operations, allgcrefs)
-        jump = operations[-1]
-        loop_consts = self._compute_loop_consts(inputargs, jump, looptoken)
-        self.loop_consts = loop_consts
-        return self._process_inputargs(inputargs), operations
+        operations, useful = self._prepare(inputargs, operations, allgcrefs)
+        return self._process_inputargs(inputargs, useful), operations
 
     def prepare_bridge(self, prev_depths, inputargs, arglocs, operations,
                        allgcrefs):
-        operations = self._prepare(inputargs, operations, allgcrefs)
-        self.loop_consts = {}
+        operations, _ = self._prepare(inputargs, operations, allgcrefs)
         self._update_bindings(arglocs, inputargs)
         self.fm.frame_depth = prev_depths[0]
         self.param_depth = prev_depths[1]
@@ -196,7 +192,7 @@
     def reserve_param(self, n):
         self.param_depth = max(self.param_depth, n)
 
-    def _process_inputargs(self, inputargs):
+    def _process_inputargs(self, inputargs, useful):
         # XXX we can sort out here by longevity if we need something
         # more optimal
         floatlocs = [None] * len(inputargs)
@@ -212,7 +208,7 @@
             arg = inputargs[i]
             assert not isinstance(arg, Const)
             reg = None
-            if arg not in self.loop_consts and self.longevity[arg][1] > -1:
+            if self.longevity[arg][1] > -1 and arg in useful:
                 if arg.type == FLOAT:
                     # xxx is it really a good idea?  at the first CALL they
                     # will all be flushed anyway
@@ -288,15 +284,15 @@
         else:
             return self.xrm.make_sure_var_in_reg(var, forbidden_vars)
 
-    def _compute_loop_consts(self, inputargs, jump, looptoken):
-        if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
-            loop_consts = {}
-        else:
-            loop_consts = {}
-            for i in range(len(inputargs)):
-                if inputargs[i] is jump.getarg(i):
-                    loop_consts[inputargs[i]] = i
-        return loop_consts
+    #def _compute_loop_consts(self, inputargs, jump, looptoken):
+    #    if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
+    #        loop_consts = {}
+    #    else:
+    #        loop_consts = {}
+    #        for i in range(len(inputargs)):
+    #            if inputargs[i] is jump.getarg(i):
+    #                loop_consts[inputargs[i]] = i
+    #    return loop_consts
 
     def _update_bindings(self, locs, inputargs):
         # XXX this should probably go to llsupport/regalloc.py
@@ -451,8 +447,14 @@
     def _compute_vars_longevity(self, inputargs, operations):
         # compute a dictionary that maps variables to index in
         # operations that is a "last-time-seen"
+
+        # returns a pair longevity/useful. Non-useful variables are ones that
+        # never appear in the assembler or it does not matter if they appear on
+        # stack or in registers. Main example is loop arguments that go
+        # only to guard operations or to jump or to finish
         produced = {}
         last_used = {}
+        useful = {}
         for i in range(len(operations)-1, -1, -1):
             op = operations[i]
             if op.result:
@@ -460,8 +462,11 @@
                     continue
                 assert op.result not in produced
                 produced[op.result] = i
+            opnum = op.getopnum()
             for j in range(op.numargs()):
                 arg = op.getarg(j)
+                if opnum != rop.JUMP and opnum != rop.FINISH:
+                    useful[arg] = None
                 if isinstance(arg, Box) and arg not in last_used:
                     last_used[arg] = i
             if op.is_guard():
@@ -487,7 +492,7 @@
                 longevity[arg] = (0, last_used[arg])
                 del last_used[arg]
         assert len(last_used) == 0
-        return longevity
+        return longevity, useful
 
     def loc(self, v):
         if v is None: # xxx kludgy
diff --git a/pypy/jit/backend/x86/test/test_regalloc.py b/pypy/jit/backend/x86/test/test_regalloc.py
--- a/pypy/jit/backend/x86/test/test_regalloc.py
+++ b/pypy/jit/backend/x86/test/test_regalloc.py
@@ -153,6 +153,13 @@
             self.cpu.execute_token(looptoken)
         return loop
 
+    def prepare_loop(self, ops):
+        loop = self.parse(ops)
+        regalloc = RegAlloc(self.cpu.assembler, False)
+        regalloc.prepare_loop(loop.inputargs, loop.operations,
+                              loop.token, [])
+        return regalloc
+
     def getint(self, index):
         return self.cpu.get_latest_value_int(index)
 
@@ -434,6 +441,35 @@
         self.run(loop)
         assert self.getints(9) == range(9)
 
+    def test_loopargs(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        jump(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+
+    def test_loopargs_2(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        finish(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+
+    def test_loopargs_3(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        guard_true(i4) [i0, i1, i2, i3, i4]
+        jump(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+    
+
 class TestRegallocCompOps(BaseTestRegalloc):
     
     def test_cmp_op_0(self):
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -457,6 +457,46 @@
     def test_compile_framework_7(self):
         self.run('compile_framework_7')
 
+    def define_compile_framework_7_interior(cls):
+        # Array of structs containing pointers (test the write barrier
+        # for setinteriorfield_gc)
+        S = lltype.GcStruct('S', ('i', lltype.Signed))
+        A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
+                                                  ('y', lltype.Ptr(S)),
+                                                  ('z', lltype.Ptr(S))))
+        class Glob:
+            a = lltype.nullptr(A)
+        glob = Glob()
+        #
+        def make_s(i):
+            s = lltype.malloc(S)
+            s.i = i
+            return s
+        #
+        @unroll_safe
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            a = glob.a
+            if not a:
+                a = glob.a = lltype.malloc(A, 10)
+            i = 0
+            while i < 10:
+                a[i].x = make_s(n + i * 100 + 1)
+                a[i].y = make_s(n + i * 100 + 2)
+                a[i].z = make_s(n + i * 100 + 3)
+                i += 1
+            i = 0
+            while i < 10:
+                check(a[i].x.i == n + i * 100 + 1)
+                check(a[i].y.i == n + i * 100 + 2)
+                check(a[i].z.i == n + i * 100 + 3)
+                i += 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        f(123, *[None]*11)  # check that the check() are ok
+        return None, f, None
+
+    def test_compile_framework_7_interior(self):
+        self.run('compile_framework_7_interior')
+
     def define_compile_framework_8(cls):
         # Array of pointers, of unknown length (test write_barrier_from_array)
         def before(n, x):
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -241,12 +241,15 @@
         return op.opname == 'jit_force_quasi_immutable'
 
 class RandomEffectsAnalyzer(BoolGraphAnalyzer):
-    def analyze_direct_call(self, graph, seen=None):
-        if hasattr(graph, "func") and hasattr(graph.func, "_ptr"):
-            if graph.func._ptr._obj.random_effects_on_gcobjs:
+    def analyze_external_call(self, op, seen=None):
+        try:
+            funcobj = op.args[0].value._obj
+            if funcobj.random_effects_on_gcobjs:
                 return True
-        return super(RandomEffectsAnalyzer, self).analyze_direct_call(graph,
-                                                                      seen)
+        except (AttributeError, lltype.DelayedPointer):
+            return True   # better safe than sorry
+        return super(RandomEffectsAnalyzer, self).analyze_external_call(
+            op, seen)
 
     def analyze_simple_operation(self, op, graphinfo):
         return False
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -15,6 +15,8 @@
 from pypy.translator.simplify import get_funcobj
 from pypy.translator.unsimplify import varoftype
 
+class UnsupportedMallocFlags(Exception):
+    pass
 
 def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None):
     """Transform a control flow graph to make it suitable for
@@ -205,7 +207,24 @@
         if op.args[0] in self.vable_array_vars:
             self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
 
-    rewrite_op_cast_pointer = rewrite_op_same_as
+    def rewrite_op_cast_pointer(self, op):
+        newop = self.rewrite_op_same_as(op)
+        assert newop is None
+        return
+        # disabled for now
+        if (self._is_rclass_instance(op.args[0]) and
+                self._is_rclass_instance(op.result)):
+            FROM = op.args[0].concretetype.TO
+            TO = op.result.concretetype.TO
+            if lltype._castdepth(TO, FROM) > 0:
+                vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, TO)
+                const_vtable = Constant(vtable, lltype.typeOf(vtable))
+                return [None, # hack, do the right renaming from op.args[0] to op.result
+                        SpaceOperation("record_known_class", [op.args[0], const_vtable], None)]
+
+    def rewrite_op_jit_record_known_class(self, op):
+        return SpaceOperation("record_known_class", [op.args[0], op.args[1]], None)
+
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass
     def rewrite_op_cast_char_to_int(self, op): pass
@@ -481,8 +500,22 @@
 
     def rewrite_op_malloc_varsize(self, op):
         if op.args[1].value['flavor'] == 'raw':
+            d = op.args[1].value.copy()
+            d.pop('flavor')
+            add_memory_pressure = d.pop('add_memory_pressure', False)
+            zero = d.pop('zero', False)
+            track_allocation = d.pop('track_allocation', True)
+            if d:
+                raise UnsupportedMallocFlags(d)
             ARRAY = op.args[0].value
-            return self._do_builtin_call(op, 'raw_malloc',
+            name = 'raw_malloc'
+            if zero:
+                name += '_zero'
+            if add_memory_pressure:
+                name += '_add_memory_pressure'
+            if not track_allocation:
+                name += '_no_track_allocation'
+            return self._do_builtin_call(op, name,
                                          [op.args[2]],
                                          extra = (ARRAY,),
                                          extrakey = ARRAY)
@@ -1053,35 +1086,20 @@
     # jit.codewriter.support.
 
     for _op, _oopspec in [('llong_invert',  'INVERT'),
-                          ('ullong_invert', 'INVERT'),
                           ('llong_lt',      'LT'),
                           ('llong_le',      'LE'),
                           ('llong_eq',      'EQ'),
                           ('llong_ne',      'NE'),
                           ('llong_gt',      'GT'),
                           ('llong_ge',      'GE'),
-                          ('ullong_lt',     'ULT'),
-                          ('ullong_le',     'ULE'),
-                          ('ullong_eq',     'EQ'),
-                          ('ullong_ne',     'NE'),
-                          ('ullong_gt',     'UGT'),
-                          ('ullong_ge',     'UGE'),
                           ('llong_add',     'ADD'),
                           ('llong_sub',     'SUB'),
                           ('llong_mul',     'MUL'),
                           ('llong_and',     'AND'),
                           ('llong_or',      'OR'),
                           ('llong_xor',     'XOR'),
-                          ('ullong_add',    'ADD'),
-                          ('ullong_sub',    'SUB'),
-                          ('ullong_mul',    'MUL'),
-                          ('ullong_and',    'AND'),
-                          ('ullong_or',     'OR'),
-                          ('ullong_xor',    'XOR'),
                           ('llong_lshift',  'LSHIFT'),
                           ('llong_rshift',  'RSHIFT'),
-                          ('ullong_lshift', 'LSHIFT'),
-                          ('ullong_rshift', 'URSHIFT'),
                           ('cast_int_to_longlong',     'FROM_INT'),
                           ('truncate_longlong_to_int', 'TO_INT'),
                           ('cast_float_to_longlong',   'FROM_FLOAT'),
@@ -1104,6 +1122,21 @@
                           ('cast_uint_to_ulonglong',    'FROM_UINT'),
                           ('cast_float_to_ulonglong',   'FROM_FLOAT'),
                           ('cast_ulonglong_to_float',   'U_TO_FLOAT'),
+                          ('ullong_invert', 'INVERT'),
+                          ('ullong_lt',     'ULT'),
+                          ('ullong_le',     'ULE'),
+                          ('ullong_eq',     'EQ'),
+                          ('ullong_ne',     'NE'),
+                          ('ullong_gt',     'UGT'),
+                          ('ullong_ge',     'UGE'),
+                          ('ullong_add',    'ADD'),
+                          ('ullong_sub',    'SUB'),
+                          ('ullong_mul',    'MUL'),
+                          ('ullong_and',    'AND'),
+                          ('ullong_or',     'OR'),
+                          ('ullong_xor',    'XOR'),
+                          ('ullong_lshift', 'LSHIFT'),
+                          ('ullong_rshift', 'URSHIFT'),
                          ]:
         exec py.code.Source('''
             def rewrite_op_%s(self, op):
@@ -1134,7 +1167,7 @@
 
     def rewrite_op_llong_is_true(self, op):
         v = varoftype(op.args[0].concretetype)
-        op0 = SpaceOperation('cast_int_to_longlong',
+        op0 = SpaceOperation('cast_primitive',
                              [Constant(0, lltype.Signed)],
                              v)
         args = [op.args[0], v]
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -258,6 +258,9 @@
     y = ~r_ulonglong(xll)
     return u_to_longlong(y)
 
+def _ll_1_ullong_invert(xull):
+    return ~xull
+
 def _ll_2_llong_lt(xll, yll):
     return xll < yll
 
@@ -276,16 +279,22 @@
 def _ll_2_llong_ge(xll, yll):
     return xll >= yll
 
-def _ll_2_llong_ult(xull, yull):
+def _ll_2_ullong_eq(xull, yull):
+    return xull == yull
+
+def _ll_2_ullong_ne(xull, yull):
+    return xull != yull
+
+def _ll_2_ullong_ult(xull, yull):
     return xull < yull
 
-def _ll_2_llong_ule(xull, yull):
+def _ll_2_ullong_ule(xull, yull):
     return xull <= yull
 
-def _ll_2_llong_ugt(xull, yull):
+def _ll_2_ullong_ugt(xull, yull):
     return xull > yull
 
-def _ll_2_llong_uge(xull, yull):
+def _ll_2_ullong_uge(xull, yull):
     return xull >= yull
 
 def _ll_2_llong_add(xll, yll):
@@ -312,14 +321,41 @@
     z = r_ulonglong(xll) ^ r_ulonglong(yll)
     return u_to_longlong(z)
 
+def _ll_2_ullong_add(xull, yull):
+    z = (xull) + (yull)
+    return (z)
+
+def _ll_2_ullong_sub(xull, yull):
+    z = (xull) - (yull)
+    return (z)
+
+def _ll_2_ullong_mul(xull, yull):
+    z = (xull) * (yull)
+    return (z)
+
+def _ll_2_ullong_and(xull, yull):
+    z = (xull) & (yull)
+    return (z)
+
+def _ll_2_ullong_or(xull, yull):
+    z = (xull) | (yull)
+    return (z)
+
+def _ll_2_ullong_xor(xull, yull):
+    z = (xull) ^ (yull)
+    return (z)
+
 def _ll_2_llong_lshift(xll, y):
     z = r_ulonglong(xll) << y
     return u_to_longlong(z)
 
+def _ll_2_ullong_lshift(xull, y):
+    return xull << y
+
 def _ll_2_llong_rshift(xll, y):
     return xll >> y
 
-def _ll_2_llong_urshift(xull, y):
+def _ll_2_ullong_urshift(xull, y):
     return xull >> y
 
 def _ll_1_llong_from_int(x):
@@ -563,10 +599,21 @@
             return p
         return _ll_0_alloc_with_del
 
-    def build_ll_1_raw_malloc(ARRAY):
-        def _ll_1_raw_malloc(n):
-            return lltype.malloc(ARRAY, n, flavor='raw')
-        return _ll_1_raw_malloc
+    def build_raw_malloc_builder(zero=False, add_memory_pressure=False, track_allocation=True):
+        def build_ll_1_raw_malloc(ARRAY):
+            def _ll_1_raw_malloc(n):
+                return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure)
+            return _ll_1_raw_malloc
+        return build_ll_1_raw_malloc
+
+    build_ll_1_raw_malloc = build_raw_malloc_builder()
+    build_ll_1_raw_malloc_zero = build_raw_malloc_builder(zero=True)
+    build_ll_1_raw_malloc_zero_add_memory_pressure = build_raw_malloc_builder(zero=True, add_memory_pressure=True)
+    build_ll_1_raw_malloc_add_memory_pressure = build_raw_malloc_builder(add_memory_pressure=True)
+    build_ll_1_raw_malloc_no_track_allocation = build_raw_malloc_builder(track_allocation=False)
+    build_ll_1_raw_malloc_zero_no_track_allocation = build_raw_malloc_builder(zero=True, track_allocation=False)
+    build_ll_1_raw_malloc_zero_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(zero=True, add_memory_pressure=True, track_allocation=False)
+    build_ll_1_raw_malloc_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(add_memory_pressure=True, track_allocation=False)
 
     def build_ll_1_raw_free(ARRAY):
         def _ll_1_raw_free(p):
diff --git a/pypy/jit/codewriter/test/test_call.py b/pypy/jit/codewriter/test/test_call.py
--- a/pypy/jit/codewriter/test/test_call.py
+++ b/pypy/jit/codewriter/test/test_call.py
@@ -192,3 +192,21 @@
     [op] = block.operations
     call_descr = cc.getcalldescr(op)
     assert call_descr.extrainfo.has_random_effects()
+
+def test_random_effects_on_stacklet_switch():
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
+    from pypy.rlib._rffi_stacklet import switch, thread_handle, handle
+    @jit.dont_look_inside
+    def f():
+        switch(rffi.cast(thread_handle, 0), rffi.cast(handle, 0))
+
+    rtyper = support.annotate(f, [])
+    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+    cc = CallControl(LLtypeCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+    res = cc.find_all_graphs(FakePolicy())
+
+    [f_graph] = [x for x in res if x.func is f]
+    [block, _] = list(f_graph.iterblocks())
+    op = block.operations[-1]
+    call_descr = cc.getcalldescr(op)
+    assert call_descr.extrainfo.has_random_effects()
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1,3 +1,5 @@
+
+import py
 import random
 try:
     from itertools import product
@@ -15,12 +17,12 @@
 
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker, effectinfo
 from pypy.jit.codewriter.flatten import ListOfKind
-from pypy.jit.codewriter.jtransform import Transformer
+from pypy.jit.codewriter.jtransform import Transformer, UnsupportedMallocFlags
 from pypy.jit.metainterp.history import getkind
 
 def const(x):
@@ -538,6 +540,44 @@
     assert op1.opname == '-live-'
     assert op1.args == []
 
+def test_raw_malloc():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw'}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_zero():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'zero': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc_zero'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_unsupported_flag():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'unsupported_flag': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    py.test.raises(UnsupportedMallocFlags, tr.rewrite_operation, op)
+
 def test_rename_on_links():
     v1 = Variable()
     v2 = Variable(); v2.concretetype = llmemory.Address
@@ -1140,4 +1180,4 @@
     assert op1.opname == 'mark_opaque_ptr'
     assert op1.args == [v1]
     assert op1.result is None
-    assert op2 is None
\ No newline at end of file
+    assert op2 is None
diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -78,7 +78,7 @@
             oplist = tr.rewrite_operation(op)
             assert len(oplist) == 2
             assert oplist[0].opname == 'residual_call_irf_f'
-            assert oplist[0].args[0].value == 'llong_from_int'
+            assert oplist[0].args[0].value == opname.split('_')[0]+'_from_int'
             assert oplist[0].args[1] == 'calldescr-84'
             assert list(oplist[0].args[2]) == [const(0)]
             assert list(oplist[0].args[3]) == []
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -518,6 +518,9 @@
     @arguments("r")
     def bhimpl_mark_opaque_ptr(a):
         pass
+    @arguments("r", "i")
+    def bhimpl_record_known_class(a, b):
+        pass
 
     @arguments("i", returns="i")
     def bhimpl_int_copy(a):
diff --git a/pypy/jit/metainterp/gc.py b/pypy/jit/metainterp/gc.py
--- a/pypy/jit/metainterp/gc.py
+++ b/pypy/jit/metainterp/gc.py
@@ -7,6 +7,9 @@
         self.config = config
 
 
+class GC_none(GcDescription):
+    malloc_zero_filled = True
+
 class GC_boehm(GcDescription):
     malloc_zero_filled = True
 
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -1071,6 +1071,25 @@
         # a jump back to itself and possibly a few bridges ending with finnish.
         # Only the operations within the loop formed by that single jump will
         # be counted.
+
+        # XXX hacked version, ignore and remove me when jit-targets is merged.
+        loops = self.get_all_loops()
+        loops = [loop for loop in loops if 'Preamble' not in repr(loop)] #XXX
+        assert len(loops) == 1
+        loop, = loops
+        jumpop = loop.operations[-1]
+        assert jumpop.getopnum() == rop.JUMP
+        insns = {}
+        for op in loop.operations:
+            opname = op.getopname()
+            insns[opname] = insns.get(opname, 0) + 1
+        return self._check_insns(insns, expected, check)
+
+    def check_simple_loop(self, expected=None, **check):
+        # Usefull in the simplest case when we have only one trace ending with
+        # a jump back to itself and possibly a few bridges ending with finnish.
+        # Only the operations within the loop formed by that single jump will
+        # be counted.
         loops = self.get_all_loops()
         assert len(loops) == 1
         loop = loops[0]
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -7,7 +7,7 @@
 from pypy.rlib.libffi import Func
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rpython.lltypesystem import llmemory
+from pypy.rpython.lltypesystem import llmemory, rffi
 
 
 class FuncInfo(object):
@@ -237,7 +237,7 @@
         else:
             assert False, "unsupported ffitype or kind"
         #
-        fieldsize = ffitype.c_size
+        fieldsize = rffi.getintfield(ffitype, 'c_size')
         return self.optimizer.cpu.interiorfielddescrof_dynamic(
             offset, width, fieldsize, is_pointer, is_float, is_signed
         )
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -565,9 +565,12 @@
         descr = op.getdescr()
         assert isinstance(descr, compile.ResumeGuardDescr)
         modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
-        newboxes = modifier.finish(self.values, self.pendingfields)
-        if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
-            compile.giveup()
+        try:
+            newboxes = modifier.finish(self.values, self.pendingfields)
+            if len(newboxes) > self.metainterp_sd.options.failargs_limit:
+                raise resume.TagOverflow
+        except resume.TagOverflow:
+            raise compile.giveup()
         descr.store_final_boxes(op, newboxes)
         #
         if op.getopnum() == rop.GUARD_VALUE:
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -260,6 +260,16 @@
     def optimize_GUARD_FALSE(self, op):
         self.optimize_guard(op, CONST_0)
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        value = self.getvalue(op.getarg(0))
+        expectedclassbox = op.getarg(1)
+        assert isinstance(expectedclassbox, Const)
+        realclassbox = value.get_constant_class(self.optimizer.cpu)
+        if realclassbox is not None:
+            assert realclassbox.same_constant(expectedclassbox)
+            return
+        value.make_constant_class(expectedclassbox, None)
+
     def optimize_GUARD_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
         expectedclassbox = op.getarg(1)
@@ -481,6 +491,9 @@
         self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0))
         self.emit_operation(op)
 
+    def optimize_SAME_AS(self, op):
+        self.make_equal_to(op.result, self.getvalue(op.getarg(0)))
+
 dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
         default=OptRewrite.emit_operation)
 optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -31,6 +31,9 @@
     def optimize_MARK_OPAQUE_PTR(self, op):
         pass
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        pass
+
     def optimize_LABEL(self, op):
         self.last_label_descr = op.getdescr()
         self.emit_operation(op)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -6508,6 +6508,21 @@
         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
 
+    def test_record_known_class(self):
+        ops = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        record_known_class(p1, ConstClass(node_vtable))
+        guard_class(p1, ConstClass(node_vtable)) []
+        jump(p1)
+        """
+        expected = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        jump(p1)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_quasi_immut(self):
         ops = """
         [p0, p1, i0]
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -242,6 +242,18 @@
     def opimpl_mark_opaque_ptr(self, box):
         return self.execute(rop.MARK_OPAQUE_PTR, box)
 
+    @arguments("box", "box")
+    def opimpl_record_known_class(self, box, clsbox):
+        from pypy.rpython.lltypesystem import llmemory
+        if self.metainterp.heapcache.is_class_known(box):
+            return
+        adr = clsbox.getaddr()
+        bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
+        if bounding_class.subclassrange_max - bounding_class.subclassrange_min == 1:
+            # precise class knowledge, this can be used
+            self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
+            self.metainterp.heapcache.class_now_known(box)
+
     @arguments("box")
     def _opimpl_any_return(self, box):
         self.metainterp.finishframe(box)
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -496,6 +496,7 @@
     'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
     'COPYUNICODECONTENT/5',
     'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
+    'RECORD_KNOWN_CLASS/2',   # [objptr, clsptr]
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -93,12 +93,14 @@
 
 TAGMASK = 3
 
+class TagOverflow(Exception):
+    pass
+
 def tag(value, tagbits):
-    if tagbits >> 2:
-        raise ValueError
+    assert 0 <= tagbits <= 3
     sx = value >> 13
     if sx != 0 and sx != -1:
-        raise ValueError
+        raise TagOverflow
     return rffi.r_short(value<<2|tagbits)
 
 def untag(value):
@@ -153,7 +155,7 @@
                 return self._newconst(const)
             try:
                 return tag(val, TAGINT)
-            except ValueError:
+            except TagOverflow:
                 pass
             tagged = self.large_ints.get(val, UNASSIGNED)
             if not tagged_eq(tagged, UNASSIGNED):
@@ -429,8 +431,7 @@
                 fieldnum = self._gettagged(fieldbox)
                 # the index is limited to 2147483647 (64-bit machines only)
                 if itemindex > 2147483647:
-                    from pypy.jit.metainterp import compile
-                    compile.giveup()
+                    raise TagOverflow
                 itemindex = rffi.cast(rffi.INT, itemindex)
                 #
                 rd_pendingfields[i].lldescr  = lldescr
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -14,7 +14,7 @@
 from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
     loop_invariant, elidable, promote, jit_debug, assert_green,
     AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
-    isconstant, isvirtual, promote_string, set_param)
+    isconstant, isvirtual, promote_string, set_param, record_known_class)
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.ootypesystem import ootype
@@ -3537,6 +3537,132 @@
         self.interp_operations(f, [5], translationoptions=translationoptions)
 
 
+    def test_annotation_gives_class_knowledge_to_tracer(self):
+        py.test.skip("disabled")
+        class Base(object):
+            pass
+        class A(Base):
+            def f(self):
+                return self.a
+            def g(self):
+                return self.a + 1
+        class B(Base):
+            def f(self):
+                return self.b
+            def g(self):
+                return self.b + 1
+        class C(B):
+            def f(self):
+                self.c += 1
+                return self.c
+            def g(self):
+                return self.c + 1
+        @dont_look_inside
+        def make(x):
+            if x > 0:
+                a = A()
+                a.a = x + 1
+            elif x < 0:
+                a = B()
+                a.b = -x
+            else:
+                a = C()
+                a.c = 10
+            return a
+        def f(x):
+            a = make(x)
+            if x > 0:
+                assert isinstance(a, A)
+                z = a.f()
+            elif x < 0:
+                assert isinstance(a, B)
+                z = a.f()
+            else:
+                assert isinstance(a, C)
+                z = a.f()
+            return z + a.g()
+        res1 = f(6)
+        res2 = self.interp_operations(f, [6])
+        assert res1 == res2
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+        res1 = f(-6)
+        res2 = self.interp_operations(f, [-6])
+        assert res1 == res2
+        # cannot use record_known_class here, because B has a subclass
+        self.check_operations_history(guard_class=1)
+
+        res1 = f(0)
+        res2 = self.interp_operations(f, [0])
+        assert res1 == res2
+        # here it works again
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+    def test_give_class_knowledge_to_tracer_explicitly(self):
+        from pypy.rpython.lltypesystem.lloperation import llop
+        class Base(object):
+            def f(self):
+                raise NotImplementedError
+            def g(self):
+                raise NotImplementedError
+        class A(Base):
+            def f(self):
+                return self.a
+            def g(self):
+                return self.a + 1
+        class B(Base):
+            def f(self):
+                return self.b
+            def g(self):
+                return self.b + 1
+        class C(B):
+            def f(self):
+                self.c += 1
+                return self.c
+            def g(self):
+                return self.c + 1
+        @dont_look_inside
+        def make(x):
+            if x > 0:
+                a = A()
+                a.a = x + 1
+            elif x < 0:
+                a = B()
+                a.b = -x
+            else:
+                a = C()
+                a.c = 10
+            return a
+        def f(x):
+            a = make(x)
+            if x > 0:
+                record_known_class(a, A)
+                z = a.f()
+            elif x < 0:
+                record_known_class(a, B)
+                z = a.f()
+            else:
+                record_known_class(a, C)
+                z = a.f()
+            return z + a.g()
+        res1 = f(6)
+        res2 = self.interp_operations(f, [6])
+        assert res1 == res2
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+        res1 = f(-6)
+        res2 = self.interp_operations(f, [-6])
+        assert res1 == res2
+        # cannot use record_known_class here, because B has a subclass
+        self.check_operations_history(guard_class=1)
+
+        res1 = f(0)
+        res2 = self.interp_operations(f, [0])
+        assert res1 == res2
+        # here it works again
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     def test_tagged(self):
         from pypy.rlib.objectmodel import UnboxedValue
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -23,11 +23,11 @@
     assert tag(-3, 2) == rffi.r_short(-3<<2|2)
     assert tag((1<<13)-1, 3) == rffi.r_short(((1<<15)-1)|3)
     assert tag(-1<<13, 3) == rffi.r_short((-1<<15)|3)
-    py.test.raises(ValueError, tag, 3, 5)
-    py.test.raises(ValueError, tag, 1<<13, 0)
-    py.test.raises(ValueError, tag, (1<<13)+1, 0)
-    py.test.raises(ValueError, tag, (-1<<13)-1, 0)
-    py.test.raises(ValueError, tag, (-1<<13)-5, 0)
+    py.test.raises(AssertionError, tag, 3, 5)
+    py.test.raises(TagOverflow, tag, 1<<13, 0)
+    py.test.raises(TagOverflow, tag, (1<<13)+1, 0)
+    py.test.raises(TagOverflow, tag, (-1<<13)-1, 0)
+    py.test.raises(TagOverflow, tag, (-1<<13)-5, 0)
 
 def test_untag():
     assert untag(tag(3, 1)) == (3, 1)
@@ -1318,8 +1318,7 @@
     assert rffi.cast(lltype.Signed, pf[1].fieldnum) == 1062
     assert rffi.cast(lltype.Signed, pf[1].itemindex) == 2147483647
     #
-    from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole
-    py.test.raises(SwitchToBlackhole, modifier._add_pending_fields,
+    py.test.raises(TagOverflow, modifier._add_pending_fields,
                    [(array_a, 42, 63, 2147483648)])
 
 def test_resume_reader_fields_and_arrayitems():
diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -615,7 +615,7 @@
             return node.value
         res = self.meta_interp(f, [48, 3], policy=StopAtXPolicy(externfn))
         assert res == f(48, 3)
-        self.check_trace_count(3)
+        self.check_trace_count(4)
         res = self.meta_interp(f, [40, 3], policy=StopAtXPolicy(externfn))
         assert res == f(40, 3)
         self.check_trace_count(3)
@@ -764,6 +764,27 @@
         res = self.meta_interp(f, [0x1F, 0x11])
         assert res == f(0x1F, 0x11)
 
+    def test_duplicated_virtual(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'node1', 'node2'])
+        def f(n):
+            node1 = self._new()
+            node1.value = 0
+            node2 = self._new()
+            node2.value = 1
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n, node1=node1, node2=node2)
+                next = self._new()
+                next.value = node1.value + node2.value + n
+                node1 = next
+                node2 = next
+                n -= 1
+            return node1.value 
+        res = self.meta_interp(f, [10])
+        assert res == f(10)
+        self.check_resops(new_with_vtable=0, new=0)
+
+        
+
     def test_retrace_not_matching_bridge(self):
         @dont_look_inside
         def external(node):
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -255,10 +255,8 @@
         s_binding = self.translator.annotator.binding
         jd._portal_args_s = [s_binding(v) for v in args]
         graph = copygraph(graph)
-        graph.startblock.isstartblock = False
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
-        graph.startblock.isstartblock = True
         # a crash in the following checkgraph() means that you forgot
         # to list some variable in greens=[] or reds=[] in JitDriver,
         # or that a jit_merge_point() takes a constant as an argument.
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -27,6 +27,7 @@
         'builtinify'                : 'interp_magic.builtinify',
         'lookup_special'            : 'interp_magic.lookup_special',
         'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
+        'list_strategy'             : 'interp_magic.list_strategy',
     }
 
     submodules = {
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -5,7 +5,6 @@
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import IndexCache
 
-
 def internal_repr(space, w_object):
     return space.wrap('%r' % (w_object,))
 
@@ -73,3 +72,11 @@
 
 def do_what_I_mean(space):
     return space.wrap(42)
+
+def list_strategy(space, w_list):
+    from pypy.objspace.std.listobject import W_ListObject
+    if isinstance(w_list, W_ListObject):
+        return space.wrap(w_list.strategy._applevel_repr)
+    else:
+        w_msg = space.wrap("Can only get the list strategy of a list")
+        raise OperationError(space.w_TypeError, w_msg)
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -5,7 +5,7 @@
     def setup_class(cls):
         if option.runappdirect:
             py.test.skip("does not make sense on pypy-c")
-        cls.space = gettestobjspace(**{"objspace.usemodules.select": False})
+        cls.space = gettestobjspace(**{"objspace.usemodules.select": False, "objspace.std.withrangelist": True})
 
     def test__isfake(self):
         from __pypy__ import isfake
@@ -54,3 +54,21 @@
         from __pypy__ import do_what_I_mean
         x = do_what_I_mean()
         assert x == 42
+
+    def test_list_strategy(self):
+        from __pypy__ import list_strategy
+
+        l = [1, 2, 3]
+        assert list_strategy(l) == "int"
+        l = ["a", "b", "c"]
+        assert list_strategy(l) == "str"
+        l = [1.1, 2.2, 3.3]
+        assert list_strategy(l) == "float"
+        l = range(3)
+        assert list_strategy(l) == "range"
+        l = [1, "b", 3]
+        assert list_strategy(l) == "object"
+        l = []
+        assert list_strategy(l) == "empty"
+        o = 5
+        raises(TypeError, list_strategy, 5)
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -67,10 +67,7 @@
         if self.unicodedata_handler:
             return self.unicodedata_handler
         try:
-            w_builtin = space.getbuiltinmodule('__builtin__')
-            w_import = space.getattr(w_builtin, space.wrap("__import__"))
-            w_unicodedata = space.call_function(w_import,
-                                                space.wrap("unicodedata"))
+            w_unicodedata = space.getbuiltinmodule("unicodedata")
             w_getcode = space.getattr(w_unicodedata, space.wrap("_get_code"))
         except OperationError:
             return None
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -100,7 +100,6 @@
 
         res, newbuf = self.do_recv_string(
             space, self.BUFFER_SIZE, maxlength)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 return space.wrap(rffi.charpsize2str(newbuf, res))
@@ -117,7 +116,6 @@
 
         res, newbuf = self.do_recv_string(
             space, length - offset, PY_SSIZE_T_MAX)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 raise BufferTooShort(space, space.wrap(
@@ -148,7 +146,6 @@
 
         res, newbuf = self.do_recv_string(
             space, self.BUFFER_SIZE, PY_SSIZE_T_MAX)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 w_received = space.wrap(rffi.charpsize2str(newbuf, res))
@@ -413,7 +410,7 @@
                                self.buffer, min(self.BUFFER_SIZE, buflength),
                                read_ptr, rffi.NULL)
             if result:
-                return read_ptr[0], lltype.nullptr(rffi.CCHARP.TO)
+                return intmask(read_ptr[0]), lltype.nullptr(rffi.CCHARP.TO)
 
             err = rwin32.GetLastError()
             if err == ERROR_BROKEN_PIPE:
@@ -476,7 +473,7 @@
         block = timeout < 0
         if not block:
             # XXX does not check for overflow
-            deadline = _GetTickCount() + int(1000 * timeout + 0.5)
+            deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5)
         else:
             deadline = 0
 
@@ -500,7 +497,7 @@
                 return True
 
             if not block:
-                now = _GetTickCount()
+                now = intmask(_GetTickCount())
                 if now > deadline:
                     return False
                 diff = deadline - now
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -235,7 +235,7 @@
             elif timeout >= 0.5 * rwin32.INFINITE: # 25 days
                 raise OperationError(space.w_OverflowError,
                                      space.wrap("timeout is too large"))
-            full_msecs = int(timeout + 0.5)
+            full_msecs = r_uint(int(timeout + 0.5))
 
         # check whether we can acquire without blocking
         res = rwin32.WaitForSingleObject(self.handle, 0)
@@ -243,7 +243,7 @@
         if res != rwin32.WAIT_TIMEOUT:
             return True
 
-        msecs = r_uint(full_msecs)
+        msecs = full_msecs
         start = _GetTickCount()
 
         while True:
@@ -269,7 +269,7 @@
                 ticks = _GetTickCount()
                 if r_uint(ticks - start) >= full_msecs:
                     return False
-                msecs = r_uint(full_msecs - (ticks - start))
+                msecs = full_msecs - r_uint(ticks - start)
 
         # handle result
         if res != rwin32.WAIT_TIMEOUT:
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -543,6 +543,7 @@
     from pypy.rlib.rwin32 import GetLastError
     return space.wrap(GetLastError())
 
-def set_last_error(space, w_error):
+ at unwrap_spec(error=int)
+def set_last_error(space, error):
     from pypy.rlib.rwin32 import SetLastError
-    SetLastError(space.uint_w(w_error))
+    SetLastError(error)
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -5,17 +5,34 @@
     applevel_name = 'numpypy'
 
     interpleveldefs = {
-        'array': 'interp_numarray.NDimArray',
+        'ndarray': 'interp_numarray.W_NDimArray',
         'dtype': 'interp_dtype.W_Dtype',
         'ufunc': 'interp_ufuncs.W_Ufunc',
 
+        'array': 'interp_numarray.array',
         'zeros': 'interp_numarray.zeros',
         'empty': 'interp_numarray.zeros',
         'ones': 'interp_numarray.ones',
+        'dot': 'interp_numarray.dot',
         'fromstring': 'interp_support.fromstring',
+        'flatiter': 'interp_numarray.W_FlatIterator',
 
-        'True_': 'space.w_True',
-        'False_': 'space.w_False',
+        'True_': 'types.Bool.True',
+        'False_': 'types.Bool.False',
+
+        'generic': 'interp_boxes.W_GenericBox',
+        'number': 'interp_boxes.W_NumberBox',
+        'integer': 'interp_boxes.W_IntegerBox',
+        'signedinteger': 'interp_boxes.W_SignedIntegerBox',
+        'bool_': 'interp_boxes.W_BoolBox',
+        'int8': 'interp_boxes.W_Int8Box',
+        'int16': 'interp_boxes.W_Int16Box',
+        'int32': 'interp_boxes.W_Int32Box',
+        'int64': 'interp_boxes.W_Int64Box',
+        'int_': 'interp_boxes.W_LongBox',
+        'inexact': 'interp_boxes.W_InexactBox',
+        'floating': 'interp_boxes.W_FloatingBox',
+        'float64': 'interp_boxes.W_Float64Box',
     }
 
     # ufuncs
@@ -48,6 +65,7 @@
         ("sign", "sign"),
         ("sin", "sin"),
         ("subtract", "subtract"),
+        ('sqrt', 'sqrt'),
         ("tan", "tan"),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
@@ -57,4 +75,5 @@
         'mean': 'app_numpy.mean',
         'inf': 'app_numpy.inf',
         'e': 'app_numpy.e',
+        'arange': 'app_numpy.arange',
     }
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
@@ -6,12 +6,33 @@
 inf = float("inf")
 e = math.e
 
+
 def average(a):
     # This implements a weighted average, for now we don't implement the
     # weighting, just the average part!
     return mean(a)
 
+
 def mean(a):
     if not hasattr(a, "mean"):
         a = numpypy.array(a)
     return a.mean()
+
+
+def arange(start, stop=None, step=1, dtype=None):
+    '''arange([start], stop[, step], dtype=None)
+    Generate values in the half-interval [start, stop).
+    '''
+    if stop is None:
+        stop = start
+        start = 0
+    if dtype is None:
+        test = numpypy.array([start, stop, step, 0])
+        dtype = test.dtype
+    arr = numpypy.zeros(int(math.ceil((stop - start) / step)), dtype=dtype)
+    i = start
+    for j in range(arr.size):
+        arr[j] = i
+        j += 1
+        i += step
+    return arr
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,13 +3,16 @@
 It should not be imported by the module itself
 """
 
+import re
+
 from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_BoolDtype
+from pypy.module.micronumpy import interp_boxes
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
-     descr_new_array, scalar_w, NDimArray)
+     scalar_w, W_NDimArray, array)
 from pypy.module.micronumpy import interp_ufuncs
-from pypy.rlib.objectmodel import specialize
-import re
+from pypy.rlib.objectmodel import specialize, instantiate
+
 
 class BogusBytecode(Exception):
     pass
@@ -48,15 +51,12 @@
     def __init__(self):
         """NOT_RPYTHON"""
         self.fromcache = InternalSpaceCache(self).getorbuild
-        self.w_float64dtype = W_Float64Dtype(self)
 
     def issequence_w(self, w_obj):
-        return isinstance(w_obj, ListObject) or isinstance(w_obj, NDimArray)
+        return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
 
     def isinstance_w(self, w_obj, w_tp):
-        if w_obj.tp == w_tp:
-            return True
-        return False
+        return w_obj.tp == w_tp
 
     def decode_index4(self, w_idx, size):
         if isinstance(w_idx, IntObject):
@@ -69,8 +69,12 @@
             if start < 0:
                 start += size
             if stop < 0:
-                stop += size
-            return (start, stop, step, size//step)
+                stop += size + 1
+            if step < 0:
+                lgt = (stop - start + 1) / step + 1
+            else:
+                lgt = (stop - start - 1) / step + 1
+            return (start, stop, step, lgt)
 
     @specialize.argtype(1)
     def wrap(self, obj):
@@ -93,11 +97,13 @@
     fixedview = listview
 
     def float(self, w_obj):
-        assert isinstance(w_obj, FloatObject)
-        return w_obj
+        if isinstance(w_obj, FloatObject):
+            return w_obj
+        assert isinstance(w_obj, interp_boxes.W_GenericBox)
+        return self.float(w_obj.descr_float(self))
 
     def float_w(self, w_obj):
-        assert isinstance(w_obj, FloatObject)        
+        assert isinstance(w_obj, FloatObject)
         return w_obj.floatval
 
     def int_w(self, w_obj):
@@ -108,7 +114,10 @@
         raise NotImplementedError
 
     def int(self, w_obj):
-        return w_obj
+        if isinstance(w_obj, IntObject):
+            return w_obj
+        assert isinstance(w_obj, interp_boxes.W_GenericBox)
+        return self.int(w_obj.descr_int(self))
 
     def is_true(self, w_obj):
         assert isinstance(w_obj, BoolObject)
@@ -131,6 +140,9 @@
         assert isinstance(what, tp)
         return what
 
+    def allocate_instance(self, klass, w_subtype):
+        return instantiate(klass)
+
     def len_w(self, w_obj):
         if isinstance(w_obj, ListObject):
             return len(w_obj.items)
@@ -208,11 +220,12 @@
 
     def execute(self, interp):
         arr = interp.variables[self.name]
-        w_index = self.index.execute(interp).eval(arr.start_iter()).wrap(interp.space)
+        w_index = self.index.execute(interp)
         # cast to int
         if isinstance(w_index, FloatObject):
             w_index = IntObject(int(w_index.floatval))
-        w_val = self.expr.execute(interp).eval(arr.start_iter()).wrap(interp.space)
+        w_val = self.expr.execute(interp)
+        assert isinstance(arr, BaseArray)
         arr.descr_setitem(interp.space, w_index, w_val)
 
     def __repr__(self):
@@ -240,23 +253,28 @@
             w_rhs = self.rhs.wrap(interp.space)
         else:
             w_rhs = self.rhs.execute(interp)
+        if not isinstance(w_lhs, BaseArray):
+            # scalar
+            dtype = get_dtype_cache(interp.space).w_float64dtype
+            w_lhs = scalar_w(interp.space, dtype, w_lhs)
         assert isinstance(w_lhs, BaseArray)
         if self.name == '+':
             w_res = w_lhs.descr_add(interp.space, w_rhs)
         elif self.name == '*':
             w_res = w_lhs.descr_mul(interp.space, w_rhs)
         elif self.name == '-':
-            w_res = w_lhs.descr_sub(interp.space, w_rhs)            
+            w_res = w_lhs.descr_sub(interp.space, w_rhs)
         elif self.name == '->':
-            if isinstance(w_rhs, Scalar):
-                w_rhs = w_rhs.eval(w_rhs.start_iter()).wrap(interp.space)
-                assert isinstance(w_rhs, FloatObject)
+            assert not isinstance(w_rhs, Scalar)
+            if isinstance(w_rhs, FloatObject):
                 w_rhs = IntObject(int(w_rhs.floatval))
+            assert isinstance(w_lhs, BaseArray)
             w_res = w_lhs.descr_getitem(interp.space, w_rhs)
         else:
             raise NotImplementedError
-        if not isinstance(w_res, BaseArray):
-            dtype = interp.space.fromcache(W_Float64Dtype)
+        if (not isinstance(w_res, BaseArray) and
+            not isinstance(w_res, interp_boxes.W_GenericBox)):
+            dtype = get_dtype_cache(interp.space).w_float64dtype
             w_res = scalar_w(interp.space, dtype, w_res)
         return w_res
 
@@ -274,9 +292,7 @@
         return space.wrap(self.v)
 
     def execute(self, interp):
-        dtype = interp.space.fromcache(W_Float64Dtype)
-        assert isinstance(dtype, W_Float64Dtype)
-        return Scalar(dtype, dtype.box(self.v))
+        return interp.space.wrap(self.v)
 
 class RangeConstant(Node):
     def __init__(self, v):
@@ -284,10 +300,10 @@
 
     def execute(self, interp):
         w_list = interp.space.newlist(
-            [interp.space.wrap(float(i)) for i in range(self.v)])
-        dtype = interp.space.fromcache(W_Float64Dtype)
-        return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
-                               w_order=None)
+            [interp.space.wrap(float(i)) for i in range(self.v)]
+        )
+        dtype = get_dtype_cache(interp.space).w_float64dtype
+        return array(interp.space, w_list, w_dtype=dtype, w_order=None)
 
     def __repr__(self):
         return 'Range(%s)' % self.v
@@ -308,9 +324,8 @@
 
     def execute(self, interp):
         w_list = self.wrap(interp.space)
-        dtype = interp.space.fromcache(W_Float64Dtype)
-        return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
-                               w_order=None)
+        dtype = get_dtype_cache(interp.space).w_float64dtype
+        return array(interp.space, w_list, w_dtype=dtype, w_order=None)
 
     def __repr__(self):
         return "[" + ", ".join([repr(item) for item in self.items]) + "]"
@@ -325,6 +340,9 @@
     def wrap(self, space):
         return SliceObject(self.start, self.stop, self.step)
 
+    def execute(self, interp):
+        return SliceObject(self.start, self.stop, self.step)
+
     def __repr__(self):
         return 'slice(%s,%s,%s)' % (self.start, self.stop, self.step)
 
@@ -374,9 +392,11 @@
             if isinstance(w_res, BaseArray):
                 return w_res
             if isinstance(w_res, FloatObject):
-                dtype = interp.space.fromcache(W_Float64Dtype)
+                dtype = get_dtype_cache(interp.space).w_float64dtype
             elif isinstance(w_res, BoolObject):
-                dtype = interp.space.fromcache(W_BoolDtype)
+                dtype = get_dtype_cache(interp.space).w_booldtype
+            elif isinstance(w_res, interp_boxes.W_GenericBox):
+                dtype = w_res.get_dtype(interp.space)
             else:
                 dtype = None
             return scalar_w(interp.space, dtype, w_res)
@@ -477,8 +497,8 @@
                 else:
                     step = 1
         return SliceConstant(start, stop, step)
-            
-        
+
+
     def parse_expression(self, tokens):
         stack = []
         while tokens.remaining():
@@ -532,7 +552,7 @@
             if token.name == 'array_right':
                 return elems
             assert token.name == 'coma'
-        
+
     def parse_statement(self, tokens):
         if (tokens.get(0).name == 'identifier' and
             tokens.get(1).name == 'assign'):
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -0,0 +1,267 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.floattype import float_typedef
+from pypy.objspace.std.inttype import int_typedef
+from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.tool.sourcetools import func_with_new_name
+
+
+MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
+
+def new_dtype_getter(name):
+    def get_dtype(space):
+        from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+        return getattr(get_dtype_cache(space), "w_%sdtype" % name)
+    def new(space, w_subtype, w_value):
+        dtype = get_dtype(space)
+        return dtype.itemtype.coerce_subtype(space, w_subtype, w_value)
+    return func_with_new_name(new, name + "_box_new"), staticmethod(get_dtype)
+
+class PrimitiveBox(object):
+    _mixin_ = True
+
+    def __init__(self, value):
+        self.value = value
+
+    def convert_to(self, dtype):
+        return dtype.box(self.value)
+
+class W_GenericBox(Wrappable):
+    _attrs_ = ()
+
+    def descr__new__(space, w_subtype, __args__):
+        assert isinstance(w_subtype, W_TypeObject)
+        raise operationerrfmt(space.w_TypeError, "cannot create '%s' instances",
+            w_subtype.get_module_type_name()
+        )
+
+    def descr_str(self, space):
+        return self.descr_repr(space)
+
+    def descr_repr(self, space):
+        return space.wrap(self.get_dtype(space).itemtype.str_format(self))
+
+    def descr_int(self, space):
+        box = self.convert_to(W_LongBox.get_dtype(space))
+        assert isinstance(box, W_LongBox)
+        return space.wrap(box.value)
+
+    def descr_float(self, space):
+        box = self.convert_to(W_Float64Box.get_dtype(space))
+        assert isinstance(box, W_Float64Box)
+        return space.wrap(box.value)
+
+    def descr_nonzero(self, space):
+        dtype = self.get_dtype(space)
+        return space.wrap(dtype.itemtype.bool(self))
+
+    def _binop_impl(ufunc_name):
+        def impl(self, space, w_other):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+        return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
+
+    def _binop_right_impl(ufunc_name):
+        def impl(self, space, w_other):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+        return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
+
+    def _unaryop_impl(ufunc_name):
+        def impl(self, space):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+        return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
+
+    descr_add = _binop_impl("add")
+    descr_sub = _binop_impl("subtract")
+    descr_mul = _binop_impl("multiply")
+    descr_div = _binop_impl("divide")
+    descr_eq = _binop_impl("equal")
+    descr_ne = _binop_impl("not_equal")
+    descr_lt = _binop_impl("less")
+    descr_le = _binop_impl("less_equal")
+    descr_gt = _binop_impl("greater")
+    descr_ge = _binop_impl("greater_equal")
+
+    descr_radd = _binop_right_impl("add")
+    descr_rmul = _binop_right_impl("multiply")
+
+    descr_neg = _unaryop_impl("negative")
+    descr_abs = _unaryop_impl("absolute")
+
+
+class W_BoolBox(W_GenericBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("bool")
+
+class W_NumberBox(W_GenericBox):
+    _attrs_ = ()
+
+class W_IntegerBox(W_NumberBox):
+    pass
+
+class W_SignedIntegerBox(W_IntegerBox):
+    pass
+
+class W_UnsignedIntgerBox(W_IntegerBox):
+    pass
+
+class W_Int8Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int8")
+
+class W_UInt8Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint8")
+
+class W_Int16Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int16")
+
+class W_UInt16Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint16")
+
+class W_Int32Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int32")
+
+class W_UInt32Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint32")
+
+class W_LongBox(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("long")
+
+class W_ULongBox(W_UnsignedIntgerBox, PrimitiveBox):
+    pass
+
+class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int64")
+
+class W_UInt64Box(W_UnsignedIntgerBox, PrimitiveBox):
+    pass
+
+class W_InexactBox(W_NumberBox):
+    _attrs_ = ()
+
+class W_FloatingBox(W_InexactBox):
+    _attrs_ = ()
+
+class W_Float32Box(W_FloatingBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("float32")
+
+class W_Float64Box(W_FloatingBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("float64")
+
+
+
+W_GenericBox.typedef = TypeDef("generic",
+    __module__ = "numpypy",
+
+    __new__ = interp2app(W_GenericBox.descr__new__.im_func),
+
+    __str__ = interp2app(W_GenericBox.descr_str),
+    __repr__ = interp2app(W_GenericBox.descr_repr),
+    __int__ = interp2app(W_GenericBox.descr_int),
+    __float__ = interp2app(W_GenericBox.descr_float),
+    __nonzero__ = interp2app(W_GenericBox.descr_nonzero),
+
+    __add__ = interp2app(W_GenericBox.descr_add),
+    __sub__ = interp2app(W_GenericBox.descr_sub),
+    __mul__ = interp2app(W_GenericBox.descr_mul),
+    __div__ = interp2app(W_GenericBox.descr_div),
+
+    __radd__ = interp2app(W_GenericBox.descr_add),
+    __rmul__ = interp2app(W_GenericBox.descr_rmul),
+
+    __eq__ = interp2app(W_GenericBox.descr_eq),
+    __ne__ = interp2app(W_GenericBox.descr_ne),
+    __lt__ = interp2app(W_GenericBox.descr_lt),
+    __le__ = interp2app(W_GenericBox.descr_le),
+    __gt__ = interp2app(W_GenericBox.descr_gt),
+    __ge__ = interp2app(W_GenericBox.descr_ge),
+
+    __neg__ = interp2app(W_GenericBox.descr_neg),
+    __abs__ = interp2app(W_GenericBox.descr_abs),
+)
+
+W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_BoolBox.descr__new__.im_func),
+)
+
+W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_IntegerBox.typedef = TypeDef("integer", W_NumberBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_SignedIntegerBox.typedef = TypeDef("signedinteger", W_IntegerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int8Box.descr__new__.im_func),
+)
+
+W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int16Box.typedef = TypeDef("int16", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int16Box.descr__new__.im_func),
+)
+
+W_UInt16Box.typedef = TypeDef("uint16", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int32Box.descr__new__.im_func),
+)
+
+W_UInt32Box.typedef = TypeDef("uint32", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+if LONG_BIT == 32:
+    long_name = "int32"
+elif LONG_BIT == 64:
+    long_name = "int64"
+W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
+    __module__ = "numpypy",
+)
+
+W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int64Box.descr__new__.im_func),
+)
+
+W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_InexactBox.typedef = TypeDef("inexact", W_NumberBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_FloatingBox.typedef = TypeDef("floating", W_InexactBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef),
+    __module__ = "numpypy",
+
+    __new__ = interp2app(W_Float64Box.descr__new__.im_func),
+)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -1,16 +1,11 @@
-import functools
-import math
-
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
-from pypy.module.micronumpy import signature
-from pypy.objspace.std.floatobject import float2string
-from pypy.rlib import rarithmetic, rfloat
-from pypy.rlib.rarithmetic import LONG_BIT, widen
-from pypy.rlib.objectmodel import specialize, enforceargs
-from pypy.rlib.unroll import unrolling_iterable
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
+    interp_attrproperty, interp_attrproperty_w)
+from pypy.module.micronumpy import types, signature, interp_boxes
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.rpython.lltypesystem import lltype, rffi
 
 
@@ -19,501 +14,218 @@
 BOOLLTR = "b"
 FLOATINGLTR = "f"
 
+
+VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True})
+
 class W_Dtype(Wrappable):
-    def __init__(self, space):
-        pass
+    _immuable_fields_ = ["itemtype", "num", "kind"]
+
+    def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[]):
+        self.signature = signature.BaseSignature()
+        self.itemtype = itemtype
+        self.num = num
+        self.kind = kind
+        self.name = name
+        self.char = char
+        self.w_box_type = w_box_type
+        self.alternate_constructors = alternate_constructors
+
+    def malloc(self, length):
+        # XXX find out why test_zjit explodes with tracking of allocations
+        return lltype.malloc(VOID_STORAGE, self.itemtype.get_element_size() * length,
+            zero=True, flavor="raw",
+            track_allocation=False, add_memory_pressure=True
+        )
+
+    @specialize.argtype(1)
+    def box(self, value):
+        return self.itemtype.box(value)
+
+    def coerce(self, space, w_item):
+        return self.itemtype.coerce(space, w_item)
+
+    def getitem(self, storage, i):
+        return self.itemtype.read(storage, self.itemtype.get_element_size(), i, 0)
+
+    def setitem(self, storage, i, box):
+        self.itemtype.store(storage, self.itemtype.get_element_size(), i, 0, box)
+
+    def fill(self, storage, box, start, stop):
+        self.itemtype.fill(storage, self.itemtype.get_element_size(), box, start, stop, 0)
 
     def descr__new__(space, w_subtype, w_dtype):
+        cache = get_dtype_cache(space)
+
         if space.is_w(w_dtype, space.w_None):
-            return space.fromcache(W_Float64Dtype)
+            return cache.w_float64dtype
+        elif space.isinstance_w(w_dtype, w_subtype):
+            return w_dtype
         elif space.isinstance_w(w_dtype, space.w_str):
-            dtype = space.str_w(w_dtype)
-            for alias, dtype_class in dtypes_by_alias:
-                if alias == dtype:
-                    return space.fromcache(dtype_class)
-        elif isinstance(space.interpclass_w(w_dtype), W_Dtype):
-            return w_dtype
-        elif space.isinstance_w(w_dtype, space.w_type):
-            for typename, dtype_class in dtypes_by_apptype:
-                if space.is_w(getattr(space, "w_%s" % typename), w_dtype):
-                    return space.fromcache(dtype_class)
+            name = space.str_w(w_dtype)
+            for dtype in cache.builtin_dtypes:
+                if dtype.name == name or dtype.char == name:
+                    return dtype
+        else:
+            for dtype in cache.builtin_dtypes:
+                if w_dtype in dtype.alternate_constructors:
+                    return dtype
+                if w_dtype is dtype.w_box_type:
+                    return dtype
         raise OperationError(space.w_TypeError, space.wrap("data type not understood"))
 
+    def descr_str(self, space):
+        return space.wrap(self.name)
+
     def descr_repr(self, space):
         return space.wrap("dtype('%s')" % self.name)
 
-    def descr_str(self, space):
-        return space.wrap(self.name)
+    def descr_get_itemsize(self, space):
+        return space.wrap(self.itemtype.get_element_size())
 
     def descr_get_shape(self, space):
         return space.newtuple([])
 
-
-class BaseBox(object):
-    pass
-
-VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True}))
-
-def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype,
-    expected_size=None):
-
-    class Box(BaseBox):
-        def __init__(self, val):
-            self.val = val
-
-        def wrap(self, space):
-            val = self.val
-            if valtype is rarithmetic.r_singlefloat:
-                val = float(val)
-            return space.wrap(val)
-
-        def convert_to(self, dtype):
-            return dtype.adapt_val(self.val)
-    Box.__name__ = "%sBox" % T._name
-
-    TP = lltype.Ptr(lltype.Array(T, hints={'nolength': True}))
-    class W_LowLevelDtype(W_Dtype):
-        signature = signature.BaseSignature()
-
-        def erase(self, storage):
-            return rffi.cast(VOID_TP, storage)
-
-        def unerase(self, storage):
-            return rffi.cast(TP, storage)
-
-        @enforceargs(None, valtype)
-        def box(self, value):
-            return Box(value)
-
-        def unbox(self, box):
-            assert isinstance(box, Box)
-            return box.val
-
-        def unwrap(self, space, w_item):
-            raise NotImplementedError
-
-        def malloc(self, size):
-            # XXX find out why test_zjit explodes with tracking of allocations
-            return self.erase(lltype.malloc(TP.TO, size,
-                zero=True, flavor="raw",
-                track_allocation=False, add_memory_pressure=True
-            ))
-
-        def getitem(self, storage, i):
-            return Box(self.unerase(storage)[i])
-
-        def setitem(self, storage, i, item):
-            self.unerase(storage)[i] = self.unbox(item)
-
-        def setitem_w(self, space, storage, i, w_item):
-            self.setitem(storage, i, self.unwrap(space, w_item))
-
-        def fill(self, storage, item, start, stop):
-            storage = self.unerase(storage)
-            item = self.unbox(item)
-            for i in xrange(start, stop):
-                storage[i] = item
-
-        @specialize.argtype(1)
-        def adapt_val(self, val):
-            return self.box(rffi.cast(TP.TO.OF, val))
-
-    W_LowLevelDtype.__name__ = "W_%sDtype" % name.capitalize()
-    W_LowLevelDtype.num = num
-    W_LowLevelDtype.kind = kind
-    W_LowLevelDtype.name = name
-    W_LowLevelDtype.aliases = aliases
-    W_LowLevelDtype.applevel_types = applevel_types
-    W_LowLevelDtype.num_bytes = rffi.sizeof(T)
-    if expected_size is not None:
-        assert W_LowLevelDtype.num_bytes == expected_size
-    return W_LowLevelDtype
-
-
-def binop(func):
-    @functools.wraps(func)
-    def impl(self, v1, v2):
-        return self.adapt_val(func(self,
-            self.for_computation(self.unbox(v1)),
-            self.for_computation(self.unbox(v2)),
-        ))
-    return impl
-
-def raw_binop(func):
-    # Returns the result unwrapped.
-    @functools.wraps(func)
-    def impl(self, v1, v2):
-        return func(self,
-            self.for_computation(self.unbox(v1)),
-            self.for_computation(self.unbox(v2))
-        )
-    return impl
-
-def unaryop(func):
-    @functools.wraps(func)
-    def impl(self, v):
-        return self.adapt_val(func(self, self.for_computation(self.unbox(v))))
-    return impl
-
-class ArithmeticTypeMixin(object):
-    _mixin_ = True
-
-    @binop
-    def add(self, v1, v2):
-        return v1 + v2
-    @binop
-    def sub(self, v1, v2):
-        return v1 - v2
-    @binop
-    def mul(self, v1, v2):
-        return v1 * v2
-
-    @unaryop
-    def pos(self, v):
-        return +v
-    @unaryop
-    def neg(self, v):
-        return -v
-    @unaryop
-    def abs(self, v):
-        return abs(v)
-
-    @binop
-    def max(self, v1, v2):
-        return max(v1, v2)
-    @binop
-    def min(self, v1, v2):
-        return min(v1, v2)
-
-    def bool(self, v):
-        return bool(self.for_computation(self.unbox(v)))
-    @raw_binop
-    def eq(self, v1, v2):
-        return v1 == v2
-    @raw_binop
-    def ne(self, v1, v2):
-        return v1 != v2
-    @raw_binop
-    def lt(self, v1, v2):
-        return v1 < v2
-    @raw_binop
-    def le(self, v1, v2):
-        return v1 <= v2
-    @raw_binop
-    def gt(self, v1, v2):
-        return v1 > v2
-    @raw_binop
-    def ge(self, v1, v2):
-        return v1 >= v2
-
-
-class FloatArithmeticDtype(ArithmeticTypeMixin):
-    _mixin_ = True
-
-    def unwrap(self, space, w_item):
-        return self.adapt_val(space.float_w(space.float(w_item)))
-
-    def for_computation(self, v):
-        return float(v)
-
-    def str_format(self, item):
-        return float2string(self.for_computation(self.unbox(item)), 'g', rfloat.DTSF_STR_PRECISION)
-
-    @binop
-    def div(self, v1, v2):
-        try:
-            return v1 / v2
-        except ZeroDivisionError:
-            if v1 == v2 == 0.0:
-                return rfloat.NAN
-            return rfloat.copysign(rfloat.INFINITY, v1 * v2)
-    @binop
-    def mod(self, v1, v2):
-        return math.fmod(v1, v2)
-    @binop
-    def pow(self, v1, v2):
-        return math.pow(v1, v2)
-
-    @unaryop
-    def sign(self, v):
-        if v == 0.0:
-            return 0.0
-        return rfloat.copysign(1.0, v)
-    @unaryop
-    def reciprocal(self, v):
-        if v == 0.0:
-            return rfloat.copysign(rfloat.INFINITY, v)
-        return 1.0 / v
-    @unaryop
-    def fabs(self, v):
-        return math.fabs(v)
-    @unaryop
-    def floor(self, v):
-        return math.floor(v)
-
-    @binop
-    def copysign(self, v1, v2):
-        return math.copysign(v1, v2)
-    @unaryop
-    def exp(self, v):
-        try:
-            return math.exp(v)
-        except OverflowError:
-            return rfloat.INFINITY
-    @unaryop
-    def sin(self, v):
-        return math.sin(v)
-    @unaryop
-    def cos(self, v):
-        return math.cos(v)
-    @unaryop
-    def tan(self, v):
-        return math.tan(v)
-    @unaryop
-    def arcsin(self, v):
-        if not -1.0 <= v <= 1.0:
-            return rfloat.NAN
-        return math.asin(v)
-    @unaryop
-    def arccos(self, v):
-        if not -1.0 <= v <= 1.0:
-            return rfloat.NAN
-        return math.acos(v)
-    @unaryop
-    def arctan(self, v):
-        return math.atan(v)
-    @unaryop
-    def arcsinh(self, v):
-        return math.asinh(v)
-    @unaryop
-    def arctanh(self, v):
-        if v == 1.0 or v == -1.0:
-            return math.copysign(rfloat.INFINITY, v)
-        if not -1.0 < v < 1.0:
-            return rfloat.NAN
-        return math.atanh(v)
-
-class IntegerArithmeticDtype(ArithmeticTypeMixin):
-    _mixin_ = True
-
-    def unwrap(self, space, w_item):
-        return self.adapt_val(space.int_w(space.int(w_item)))
-
-    def for_computation(self, v):
-        return widen(v)
-
-    def str_format(self, item):
-        return str(widen(self.unbox(item)))
-
-    @binop
-    def div(self, v1, v2):
-        if v2 == 0:
-            return 0
-        return v1 / v2
-    @binop
-    def mod(self, v1, v2):
-        return v1 % v2
-
-class SignedIntegerArithmeticDtype(IntegerArithmeticDtype):
-    _mixin_ = True
-
-    @unaryop
-    def sign(self, v):
-        if v > 0:
-            return 1
-        elif v < 0:
-            return -1
-        else:
-            assert v == 0
-            return 0
-
-class UnsignedIntegerArithmeticDtype(IntegerArithmeticDtype):
-    _mixin_ = True
-
-    @unaryop
-    def sign(self, v):
-        return int(v != 0)
-
-
-W_BoolDtype = create_low_level_dtype(
-    num = 0, kind = BOOLLTR, name = "bool",
-    aliases = ["?", "bool", "bool8"],
-    applevel_types = ["bool"],
-    T = lltype.Bool,
-    valtype = bool,
-)
-class W_BoolDtype(SignedIntegerArithmeticDtype, W_BoolDtype):
-    def unwrap(self, space, w_item):
-        return self.adapt_val(space.is_true(w_item))
-
-    def str_format(self, item):
-        v = self.unbox(item)
-        return "True" if v else "False"
-
-    def for_computation(self, v):
-        return int(v)
-
-W_Int8Dtype = create_low_level_dtype(
-    num = 1, kind = SIGNEDLTR, name = "int8",
-    aliases = ["b", "int8", "i1"],
-    applevel_types = [],
-    T = rffi.SIGNEDCHAR,
-    valtype = rffi.SIGNEDCHAR._type,
-    expected_size = 1,
-)
-class W_Int8Dtype(SignedIntegerArithmeticDtype, W_Int8Dtype):
-    pass
-
-W_UInt8Dtype = create_low_level_dtype(
-    num = 2, kind = UNSIGNEDLTR, name = "uint8",
-    aliases = ["B", "uint8", "I1"],
-    applevel_types = [],
-    T = rffi.UCHAR,
-    valtype = rffi.UCHAR._type,
-    expected_size = 1,
-)
-class W_UInt8Dtype(UnsignedIntegerArithmeticDtype, W_UInt8Dtype):
-    pass
-
-W_Int16Dtype = create_low_level_dtype(
-    num = 3, kind = SIGNEDLTR, name = "int16",
-    aliases = ["h", "int16", "i2"],
-    applevel_types = [],
-    T = rffi.SHORT,
-    valtype = rffi.SHORT._type,
-    expected_size = 2,
-)
-class W_Int16Dtype(SignedIntegerArithmeticDtype, W_Int16Dtype):
-    pass
-
-W_UInt16Dtype = create_low_level_dtype(
-    num = 4, kind = UNSIGNEDLTR, name = "uint16",
-    aliases = ["H", "uint16", "I2"],
-    applevel_types = [],
-    T = rffi.USHORT,
-    valtype = rffi.USHORT._type,
-    expected_size = 2,
-)
-class W_UInt16Dtype(UnsignedIntegerArithmeticDtype, W_UInt16Dtype):
-    pass
-
-W_Int32Dtype = create_low_level_dtype(
-    num = 5, kind = SIGNEDLTR, name = "int32",
-    aliases = ["i", "int32", "i4"],
-    applevel_types = [],
-    T = rffi.INT,
-    valtype = rffi.INT._type,
-    expected_size = 4,
-)
-class W_Int32Dtype(SignedIntegerArithmeticDtype, W_Int32Dtype):
-    pass
-
-W_UInt32Dtype = create_low_level_dtype(
-    num = 6, kind = UNSIGNEDLTR, name = "uint32",
-    aliases = ["I", "uint32", "I4"],
-    applevel_types = [],
-    T = rffi.UINT,
-    valtype = rffi.UINT._type,
-    expected_size = 4,
-)
-class W_UInt32Dtype(UnsignedIntegerArithmeticDtype, W_UInt32Dtype):
-    pass
-
-W_Int64Dtype = create_low_level_dtype(
-    num = 9, kind = SIGNEDLTR, name = "int64",
-    aliases = ["q", "int64", "i8"],
-    applevel_types = ["long"],
-    T = rffi.LONGLONG,
-    valtype = rffi.LONGLONG._type,
-    expected_size = 8,
-)
-class W_Int64Dtype(SignedIntegerArithmeticDtype, W_Int64Dtype):
-    pass
-
-W_UInt64Dtype = create_low_level_dtype(
-    num = 10, kind = UNSIGNEDLTR, name = "uint64",
-    aliases = ["Q", "uint64", "I8"],
-    applevel_types = [],
-    T = rffi.ULONGLONG,
-    valtype = rffi.ULONGLONG._type,
-    expected_size = 8,
-)
-class W_UInt64Dtype(UnsignedIntegerArithmeticDtype, W_UInt64Dtype):
-    pass
-
-if LONG_BIT == 32:
-    long_dtype = W_Int32Dtype
-    ulong_dtype = W_UInt32Dtype
-elif LONG_BIT == 64:
-    long_dtype = W_Int64Dtype
-    ulong_dtype = W_UInt64Dtype
-else:
-    assert False
-
-class W_LongDtype(long_dtype):
-    num = 7
-    aliases = ["l"]
-    applevel_types = ["int"]
-
-class W_ULongDtype(ulong_dtype):
-    num = 8
-    aliases = ["L"]
-
-W_Float32Dtype = create_low_level_dtype(
-    num = 11, kind = FLOATINGLTR, name = "float32",
-    aliases = ["f", "float32", "f4"],
-    applevel_types = [],
-    T = lltype.SingleFloat,
-    valtype = rarithmetic.r_singlefloat,
-    expected_size = 4,
-)
-class W_Float32Dtype(FloatArithmeticDtype, W_Float32Dtype):
-    pass
-
-W_Float64Dtype = create_low_level_dtype(
-    num = 12, kind = FLOATINGLTR, name = "float64",
-    aliases = ["d", "float64", "f8"],
-    applevel_types = ["float"],
-    T = lltype.Float,
-    valtype = float,
-    expected_size = 8,
-)
-class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype):
-    pass
-
-ALL_DTYPES = [
-    W_BoolDtype,
-    W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype,
-    W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype,
-    W_Int64Dtype, W_UInt64Dtype,
-    W_Float32Dtype, W_Float64Dtype,
-]
-
-dtypes_by_alias = unrolling_iterable([
-    (alias, dtype)
-    for dtype in ALL_DTYPES
-    for alias in dtype.aliases
-])
-dtypes_by_apptype = unrolling_iterable([
-    (apptype, dtype)
-    for dtype in ALL_DTYPES
-    for apptype in dtype.applevel_types
-])
-dtypes_by_num_bytes = unrolling_iterable(sorted([
-    (dtype.num_bytes, dtype)
-    for dtype in ALL_DTYPES
-]))
-
 W_Dtype.typedef = TypeDef("dtype",
-    __module__ = "numpy",
+    __module__ = "numpypy",
     __new__ = interp2app(W_Dtype.descr__new__.im_func),
 
+    __str__= interp2app(W_Dtype.descr_str),
     __repr__ = interp2app(W_Dtype.descr_repr),
-    __str__ = interp2app(W_Dtype.descr_str),
 
     num = interp_attrproperty("num", cls=W_Dtype),
     kind = interp_attrproperty("kind", cls=W_Dtype),
-    itemsize = interp_attrproperty("num_bytes", cls=W_Dtype),
+    type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
+    itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
 )
 W_Dtype.typedef.acceptable_as_base_class = False
+
+class DtypeCache(object):
+    def __init__(self, space):
+        self.w_booldtype = W_Dtype(
+            types.Bool(),
+            num=0,
+            kind=BOOLLTR,
+            name="bool",
+            char="?",
+            w_box_type = space.gettypefor(interp_boxes.W_BoolBox),
+            alternate_constructors=[space.w_bool],
+        )
+        self.w_int8dtype = W_Dtype(
+            types.Int8(),
+            num=1,
+            kind=SIGNEDLTR,
+            name="int8",
+            char="b",
+            w_box_type = space.gettypefor(interp_boxes.W_Int8Box)
+        )
+        self.w_uint8dtype = W_Dtype(
+            types.UInt8(),
+            num=2,
+            kind=UNSIGNEDLTR,
+            name="uint8",
+            char="B",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt8Box),
+        )
+        self.w_int16dtype = W_Dtype(
+            types.Int16(),
+            num=3,
+            kind=SIGNEDLTR,
+            name="int16",
+            char="h",
+            w_box_type = space.gettypefor(interp_boxes.W_Int16Box),
+        )
+        self.w_uint16dtype = W_Dtype(
+            types.UInt16(),
+            num=4,
+            kind=UNSIGNEDLTR,
+            name="uint16",
+            char="H",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt16Box),
+        )
+        self.w_int32dtype = W_Dtype(
+            types.Int32(),
+            num=5,
+            kind=SIGNEDLTR,
+            name="int32",
+            char="i",
+             w_box_type = space.gettypefor(interp_boxes.W_Int32Box),
+       )
+        self.w_uint32dtype = W_Dtype(
+            types.UInt32(),
+            num=6,
+            kind=UNSIGNEDLTR,
+            name="uint32",
+            char="I",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt32Box),
+        )
+        if LONG_BIT == 32:
+            name = "int32"
+        elif LONG_BIT == 64:
+            name = "int64"
+        self.w_longdtype = W_Dtype(
+            types.Long(),
+            num=7,
+            kind=SIGNEDLTR,
+            name=name,
+            char="l",
+            w_box_type = space.gettypefor(interp_boxes.W_LongBox),
+            alternate_constructors=[space.w_int],
+        )
+        self.w_ulongdtype = W_Dtype(
+            types.ULong(),
+            num=8,
+            kind=UNSIGNEDLTR,
+            name="u" + name,
+            char="L",
+            w_box_type = space.gettypefor(interp_boxes.W_ULongBox),
+        )
+        self.w_int64dtype = W_Dtype(
+            types.Int64(),
+            num=9,
+            kind=SIGNEDLTR,
+            name="int64",
+            char="q",
+            w_box_type = space.gettypefor(interp_boxes.W_Int64Box),
+            alternate_constructors=[space.w_long],
+        )
+        self.w_uint64dtype = W_Dtype(
+            types.UInt64(),
+            num=10,
+            kind=UNSIGNEDLTR,
+            name="uint64",
+            char="Q",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt64Box),
+        )
+        self.w_float32dtype = W_Dtype(
+            types.Float32(),
+            num=11,
+            kind=FLOATINGLTR,
+            name="float32",
+            char="f",
+            w_box_type = space.gettypefor(interp_boxes.W_Float32Box),
+        )
+        self.w_float64dtype = W_Dtype(
+            types.Float64(),
+            num=12,
+            kind=FLOATINGLTR,
+            name="float64",
+            char="d",
+            w_box_type = space.gettypefor(interp_boxes.W_Float64Box),
+            alternate_constructors=[space.w_float],
+        )
+
+        self.builtin_dtypes = [
+            self.w_booldtype, self.w_int8dtype, self.w_uint8dtype,
+            self.w_int16dtype, self.w_uint16dtype, self.w_int32dtype,
+            self.w_uint32dtype, self.w_longdtype, self.w_ulongdtype,
+            self.w_int64dtype, self.w_uint64dtype, self.w_float32dtype,
+            self.w_float64dtype
+        ]
+        self.dtypes_by_num_bytes = sorted(
+            (dtype.itemtype.get_element_size(), dtype)
+            for dtype in self.builtin_dtypes
+        )
+
+def get_dtype_cache(space):
+    return space.fromcache(DtypeCache)
\ No newline at end of file
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
@@ -4,7 +4,7 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.module.micronumpy import interp_ufuncs, interp_dtype, signature
 from pypy.rlib import jit
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.objectmodel import instantiate
@@ -98,46 +98,6 @@
         endshape[i] = remainder[i]
     return endshape
 
-def descr_new_array(space, w_subtype, w_item_or_iterable, w_dtype=None,
-                    w_order=NoneNotWrapped):
-    # find scalar
-    if not space.issequence_w(w_item_or_iterable):
-        w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
-                                                      w_item_or_iterable,
-                                                      w_dtype)
-        dtype = space.interp_w(interp_dtype.W_Dtype,
-           space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
-        return scalar_w(space, dtype, w_item_or_iterable)
-    if w_order is None:
-        order = 'C'
-    else:
-        order = space.str_w(w_order)
-        if order != 'C':  # or order != 'F':
-            raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
-                                  order)
-    shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
-    # they come back in C order
-    size = len(elems_w)
-    if space.is_w(w_dtype, space.w_None):
-        w_dtype = None
-        for w_elem in elems_w:
-            w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
-                                                          w_dtype)
-            if w_dtype is space.fromcache(interp_dtype.W_Float64Dtype):
-                break
-    if w_dtype is None:
-        w_dtype = space.w_None
-    dtype = space.interp_w(interp_dtype.W_Dtype,
-        space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
-    )
-    arr = NDimArray(size, shape[:], dtype=dtype, order=order)
-    shapelen = len(shape)
-    arr_iter = arr.start_iter(arr.shape)
-    for i in range(len(elems_w)):
-        w_elem = elems_w[i]
-        dtype.setitem_w(space, arr.storage, arr_iter.offset, w_elem)
-        arr_iter = arr_iter.next(shapelen)
-    return arr
 
 # Iterators for arrays
 # --------------------
@@ -178,6 +138,25 @@
     def get_offset(self):
         return self.offset
 
+class OneDimIterator(BaseIterator):
+    def __init__(self, start, step, stop):
+        self.offset = start
+        self.step = step
+        self.size = stop * step + start
+
+    def next(self, shapelen):
+        arr = instantiate(OneDimIterator)
+        arr.size = self.size
+        arr.step = self.step
+        arr.offset = self.offset + self.step
+        return arr
+
+    def done(self):
+        return self.offset == self.size
+
+    def get_offset(self):
+        return self.offset
+
 class ViewIterator(BaseIterator):
     def __init__(self, arr):
         self.indices = [0] * len(arr.shape)
@@ -227,7 +206,7 @@
         self.strides = []
         self.backstrides = []
         for i in range(len(arr.shape)):
-            if arr.shape[i]==1:
+            if arr.shape[i] == 1:
                 self.strides.append(0)
                 self.backstrides.append(0)
             else:
@@ -312,12 +291,12 @@
     def get_offset(self):
         return 0
 
+
 class BaseArray(Wrappable):
     _attrs_ = ["invalidates", "signature", "shape", "strides", "backstrides",
                "start", 'order']
 
-    _immutable_fields_ = ['shape[*]', "strides[*]", "backstrides[*]", 'start',
-                          "order"]
+    _immutable_fields_ = ['start', "order"]
 
     strides = None
     start = 0
@@ -327,21 +306,24 @@
         self.shape = shape
         self.order = order
         if self.strides is None:
-            strides = []
-            backstrides = []
-            s = 1
-            shape_rev = shape[:]
-            if order == 'C':
-                shape_rev.reverse()
-            for sh in shape_rev:
-                strides.append(s)
-                backstrides.append(s * (sh - 1))
-                s *= sh
-            if order == 'C':
-                strides.reverse()
-                backstrides.reverse()
-            self.strides = strides[:]
-            self.backstrides = backstrides[:]
+            self.calc_strides(shape)
+
+    def calc_strides(self, shape):
+        strides = []
+        backstrides = []
+        s = 1
+        shape_rev = shape[:]
+        if self.order == 'C':
+            shape_rev.reverse()
+        for sh in shape_rev:
+            strides.append(s)
+            backstrides.append(s * (sh - 1))
+            s *= sh
+        if self.order == 'C':
+            strides.reverse()
+            backstrides.reverse()
+        self.strides = strides[:]
+        self.backstrides = backstrides[:]
 
     def invalidated(self):
         if self.invalidates:
@@ -355,6 +337,13 @@
     def add_invalidates(self, other):
         self.invalidates.append(other)
 
+    def descr__new__(space, w_subtype, w_size, w_dtype=None):
+        dtype = space.interp_w(interp_dtype.W_Dtype,
+            space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+        )
+        size, shape = _find_size_and_shape(space, w_size)
+        return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
+
     def _unaryop_impl(ufunc_name):
         def impl(self, space):
             return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
@@ -428,8 +417,8 @@
                                               self=self, dtype=dtype,
                                               i=i, result=result, idx=idx,
                                               cur_best=cur_best)
-                new_best = getattr(dtype, op_name)(cur_best, self.eval(i))
-                if dtype.ne(new_best, cur_best):
+                new_best = getattr(dtype.itemtype, op_name)(cur_best, self.eval(i))
+                if dtype.itemtype.ne(new_best, cur_best):
                     result = idx
                     cur_best = new_best
                 i = i.next(shapelen)
@@ -439,8 +428,7 @@
             size = self.find_size()
             if size == 0:
                 raise OperationError(space.w_ValueError,
-                    space.wrap("Can't call %s on zero-size arrays" \
-                            % op_name))
+                    space.wrap("Can't call %s on zero-size arrays" % op_name))
             return space.wrap(loop(self))
         return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
 
@@ -452,7 +440,7 @@
             all_driver.jit_merge_point(signature=self.signature,
                                        shapelen=shapelen, self=self,
                                        dtype=dtype, i=i)
-            if not dtype.bool(self.eval(i)):
+            if not dtype.itemtype.bool(self.eval(i)):
                 return False
             i = i.next(shapelen)
         return True
@@ -467,7 +455,7 @@
             any_driver.jit_merge_point(signature=self.signature,
                                        shapelen=shapelen, self=self,
                                        dtype=dtype, i=i)
-            if dtype.bool(self.eval(i)):
+            if dtype.itemtype.bool(self.eval(i)):
                 return True
             i = i.next(shapelen)
         return False
@@ -499,7 +487,7 @@
         return space.wrap(self.find_size())
 
     def descr_copy(self, space):
-        return space.call_function(space.gettypefor(BaseArray), self, self.find_dtype())
+        return self.get_concrete().copy()
 
     def descr_len(self, space):
         return self.get_concrete().descr_len(space)
@@ -519,8 +507,8 @@
                 res.append(')')
         else:
             concrete.to_str(space, 1, res, indent='       ')
-        if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
-            dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or \
+        if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
+            dtype is not interp_dtype.get_dtype_cache(space).w_int64dtype) or \
             not self.find_size():
             res.append(", dtype=" + dtype.name)
         res.append(")")
@@ -589,7 +577,7 @@
                         start = False
                     else:
                         builder.append(spacer)
-                    builder.append(dtype.str_format(self.getitem(item)))
+                    builder.append(dtype.itemtype.str_format(self.getitem(item)))
                     item += self.strides[0]
                 # Add a comma only if comma is False - this prevents adding two
                 # commas
@@ -602,7 +590,7 @@
                     start = False
                 else:
                     builder.append(spacer)
-                builder.append(dtype.str_format(self.getitem(item)))
+                builder.append(dtype.itemtype.str_format(self.getitem(item)))
                 item += self.strides[0]
                 i += 1
         else:
@@ -674,6 +662,7 @@
                 return False
         return True
 
+    @jit.unroll_safe
     def _prepare_slice_args(self, space, w_idx):
         if (space.isinstance_w(w_idx, space.w_int) or
             space.isinstance_w(w_idx, space.w_slice)):
@@ -684,31 +673,31 @@
     def descr_getitem(self, space, w_idx):
         if self._single_item_result(space, w_idx):
             concrete = self.get_concrete()
+            if len(concrete.shape) < 1:
+                raise OperationError(space.w_IndexError, space.wrap(
+                        "0-d arrays can't be indexed"))
             item = concrete._index_of_single_item(space, w_idx)
-            return concrete.getitem(item).wrap(space)
+            return concrete.getitem(item)
         chunks = self._prepare_slice_args(space, w_idx)
         return space.wrap(self.create_slice(space, chunks))
 
     def descr_setitem(self, space, w_idx, w_value):
         self.invalidated()
-        concrete = self.get_concrete()
         if self._single_item_result(space, w_idx):
+            concrete = self.get_concrete()
+            if len(concrete.shape) < 1:
+                raise OperationError(space.w_IndexError, space.wrap(
+                        "0-d arrays can't be indexed"))
             item = concrete._index_of_single_item(space, w_idx)
             concrete.setitem_w(space, item, w_value)
             return
-        if isinstance(w_value, BaseArray):
-            # for now we just copy if setting part of an array from
-            # part of itself. can be improved.
-            if (concrete.get_root_storage() ==
-                w_value.get_concrete().get_root_storage()):
-                w_value = space.call_function(space.gettypefor(BaseArray), w_value)
-                assert isinstance(w_value, BaseArray)
-        else:
+        if not isinstance(w_value, BaseArray):
             w_value = convert_to_array(space, w_value)
         chunks = self._prepare_slice_args(space, w_idx)
         view = self.create_slice(space, chunks)
         view.setslice(space, w_value)
 
+    @jit.unroll_safe
     def create_slice(self, space, chunks):
         if len(chunks) == 1:
             start, stop, step, lgt = chunks[0]
@@ -747,17 +736,35 @@
                          shape[:])
 
     def descr_mean(self, space):
-        return space.wrap(space.float_w(self.descr_sum(space)) / self.find_size())
+        return space.div(self.descr_sum(space), space.wrap(self.find_size()))
 
     def descr_nonzero(self, space):
-        try:
-            if self.find_size() > 1:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
-        except ValueError:
-            pass
-        return space.wrap(space.is_true(self.get_concrete().eval(
-            self.start_iter(self.shape)).wrap(space)))
+        if self.find_size() > 1:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
+        return space.wrap(space.is_true(
+            self.get_concrete().eval(self.start_iter(self.shape))
+        ))
+
+    def descr_get_transpose(self, space):
+        concrete = self.get_concrete()
+        if len(concrete.shape) < 2:
+            return space.wrap(self)
+        new_sig = signature.Signature.find_sig([
+            NDimSlice.signature, self.signature
+        ])
+        strides = []
+        backstrides = []
+        shape = []
+        for i in range(len(concrete.shape) - 1, -1, -1):
+            strides.append(concrete.strides[i])
+            backstrides.append(concrete.backstrides[i])
+            shape.append(concrete.shape[i])
+        return space.wrap(NDimSlice(concrete, new_sig, self.start, strides[:],
+                           backstrides[:], shape[:]))
+
+    def descr_get_flatiter(self, space):
+        return space.wrap(W_FlatIterator(self))
 
     def getitem(self, item):
         raise NotImplementedError
@@ -765,22 +772,22 @@
     def start_iter(self, res_shape=None):
         raise NotImplementedError
 
+    def descr_debug_repr(self, space):
+        return space.wrap(self.debug_repr())
+
 def convert_to_array(space, w_obj):
     if isinstance(w_obj, BaseArray):
         return w_obj
     elif space.issequence_w(w_obj):
         # Convert to array.
-        w_obj = space.call_function(space.gettypefor(BaseArray), w_obj)
-        assert isinstance(w_obj, BaseArray)
-        return w_obj
+        return array(space, w_obj, w_order=None)
     else:
         # If it's a scalar
         dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
         return scalar_w(space, dtype, w_obj)
 
 def scalar_w(space, dtype, w_obj):
-    assert isinstance(dtype, interp_dtype.W_Dtype)
-    return Scalar(dtype, dtype.unwrap(space, w_obj))
+    return Scalar(dtype, dtype.coerce(space, w_obj))
 
 class Scalar(BaseArray):
     """
@@ -791,12 +798,13 @@
     _attrs_ = ["dtype", "value", "shape"]
 
     def __init__(self, dtype, value):
+        self.shape = self.strides = []
         BaseArray.__init__(self, [], 'C')
         self.dtype = dtype
         self.value = value
 
     def find_size(self):
-        raise ValueError
+        return 1
 
     def get_concrete(self):
         return self
@@ -805,7 +813,7 @@
         return self.dtype
 
     def getitem(self, item):
-        return self.value
+        raise NotImplementedError
 
     def eval(self, iter):
         return self.value
@@ -814,7 +822,13 @@
         return ConstantIterator()
 
     def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        builder.append(self.dtype.str_format(self.value))
+        builder.append(self.dtype.itemtype.str_format(self.value))
+
+    def copy(self):
+        return Scalar(self.dtype, self.value)
+
+    def debug_repr(self):
+        return 'Scalar'
 
 class VirtualArray(BaseArray):
     """
@@ -834,7 +848,7 @@
         i = 0
         signature = self.signature
         result_size = self.find_size()
-        result = NDimArray(result_size, self.shape, self.find_dtype())
+        result = W_NDimArray(result_size, self.shape, self.find_dtype())
         shapelen = len(self.shape)
         i = self.start_iter()
         ri = result.start_iter()
@@ -907,6 +921,17 @@
             return self.forced_result.start_iter(res_shape)
         return Call1Iterator(self.values.start_iter(res_shape))
 
+    def debug_repr(self):
+        sig = self.signature
+        assert isinstance(sig, signature.Signature)
+        call_sig = sig.components[0]
+        assert isinstance(call_sig, signature.Call1)
+        if self.forced_result is not None:
+            return 'Call1(%s, forced=%s)' % (call_sig.name,
+                                             self.forced_result.debug_repr())
+        return 'Call1(%s, %s)' % (call_sig.name,
+                                  self.values.debug_repr())
+
 class Call2(VirtualArray):
     """
     Intermediate class for performing binary operations.
@@ -946,6 +971,18 @@
         assert isinstance(call_sig, signature.Call2)
         return call_sig.func(self.calc_dtype, lhs, rhs)
 
+    def debug_repr(self):
+        sig = self.signature
+        assert isinstance(sig, signature.Signature)
+        call_sig = sig.components[0]
+        assert isinstance(call_sig, signature.Call2)
+        if self.forced_result is not None:
+            return 'Call2(%s, forced=%s)' % (call_sig.name,
+                self.forced_result.debug_repr())
+        return 'Call2(%s, %s, %s)' % (call_sig.name,
+            self.left.debug_repr(),
+            self.right.debug_repr())
+
 class ViewArray(BaseArray):
     """
     Class for representing views of arrays, they will reflect changes of parent
@@ -985,8 +1022,6 @@
             return space.wrap(self.shape[0])
         return space.wrap(1)
 
-class VirtualView(VirtualArray):
-    pass
 
 class NDimSlice(ViewArray):
     signature = signature.BaseSignature()
@@ -1001,9 +1036,6 @@
         for sh in shape:
             self.size *= sh
 
-    def get_root_storage(self):
-        return self.parent.get_concrete().get_root_storage()
-
     def find_size(self):
         return self.size
 
@@ -1032,14 +1064,25 @@
     def start_iter(self, res_shape=None):
         if res_shape is not None and res_shape != self.shape:
             return BroadcastIterator(self, res_shape)
-        # XXX there is a possible optimization here with SingleDimViewIterator
-        #     ignore for now
+        if len(self.shape) == 1:
+            return OneDimIterator(self.start, self.strides[0], self.shape[0])
         return ViewIterator(self)
 
     def setitem(self, item, value):
         self.parent.setitem(item, value)
 
-class NDimArray(BaseArray):
+    def debug_repr(self):
+        return 'Slice(%s)' % self.parent.debug_repr()
+
+    def copy(self):
+        array = W_NDimArray(self.size, self.shape[:], self.find_dtype())
+        iter = self.start_iter()
+        while not iter.done():
+            array.setitem(iter.offset, self.getitem(iter.offset))
+            iter = iter.next(len(self.shape))
+        return array
+
+class W_NDimArray(BaseArray):
     """ A class representing contiguous array. We know that each iteration
     by say ufunc will increase the data index by one
     """
@@ -1053,9 +1096,6 @@
     def get_concrete(self):
         return self
 
-    def get_root_storage(self):
-        return self.storage
-
     def find_size(self):
         return self.size
 
@@ -1068,6 +1108,15 @@
     def eval(self, iter):
         return self.dtype.getitem(self.storage, iter.get_offset())
 
+    def copy(self):
+        array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
+        rffi.c_memcpy(
+            array.storage,
+            self.storage,
+            self.size * self.dtype.itemtype.get_element_size()
+        )
+        return array
+
     def descr_len(self, space):
         if len(self.shape):
             return space.wrap(self.shape[0])
@@ -1075,8 +1124,7 @@
             "len() of unsized object"))
 
     def setitem_w(self, space, item, w_value):
-        self.invalidated()
-        self.dtype.setitem_w(space, self.storage, item, w_value)
+        return self.setitem(item, self.dtype.coerce(space, w_value))
 
     def setitem(self, item, value):
         self.invalidated()
@@ -1089,6 +1137,9 @@
             return ArrayIterator(self.size)
         raise NotImplementedError  # use ViewIterator simply, test it
 
+    def debug_repr(self):
+        return 'Array'
+
     def __del__(self):
         lltype.free(self.storage, flavor='raw', track_allocation=False)
 
@@ -1105,27 +1156,75 @@
             shape.append(item)
     return size, shape
 
+def array(space, w_item_or_iterable, w_dtype=None, w_order=NoneNotWrapped):
+    # find scalar
+    if not space.issequence_w(w_item_or_iterable):
+        if space.is_w(w_dtype, space.w_None):
+            w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
+                                                          w_item_or_iterable)
+        dtype = space.interp_w(interp_dtype.W_Dtype,
+            space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+        )
+        return scalar_w(space, dtype, w_item_or_iterable)
+    if w_order is None:
+        order = 'C'
+    else:
+        order = space.str_w(w_order)
+        if order != 'C':  # or order != 'F':
+            raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
+                                  order)
+    shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
+    # they come back in C order
+    size = len(elems_w)
+    if space.is_w(w_dtype, space.w_None):
+        w_dtype = None
+        for w_elem in elems_w:
+            w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
+                                                          w_dtype)
+            if w_dtype is interp_dtype.get_dtype_cache(space).w_float64dtype:
+                break
+    if w_dtype is None:
+        w_dtype = space.w_None
+    dtype = space.interp_w(interp_dtype.W_Dtype,
+        space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+    )
+    arr = W_NDimArray(size, shape[:], dtype=dtype, order=order)
+    shapelen = len(shape)
+    arr_iter = arr.start_iter(arr.shape)
+    for i in range(len(elems_w)):
+        w_elem = elems_w[i]
+        dtype.setitem(arr.storage, arr_iter.offset, dtype.coerce(space, w_elem))
+        arr_iter = arr_iter.next(shapelen)
+    return arr
+
 def zeros(space, w_size, w_dtype=None):
     dtype = space.interp_w(interp_dtype.W_Dtype,
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
     size, shape = _find_size_and_shape(space, w_size)
-    return space.wrap(NDimArray(size, shape[:], dtype=dtype))
+    return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
 
 def ones(space, w_size, w_dtype=None):
     dtype = space.interp_w(interp_dtype.W_Dtype,
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
+
     size, shape = _find_size_and_shape(space, w_size)
-    arr = NDimArray(size, shape[:], dtype=dtype)
-    one = dtype.adapt_val(1)
+    arr = W_NDimArray(size, shape[:], dtype=dtype)
+    one = dtype.box(1)
     arr.dtype.fill(arr.storage, one, 0, size)
     return space.wrap(arr)
 
+def dot(space, w_obj, w_obj2):
+    w_arr = convert_to_array(space, w_obj)
+    if isinstance(w_arr, Scalar):
+        return convert_to_array(space, w_obj2).descr_dot(space, w_arr)
+    return w_arr.descr_dot(space, w_obj2)
+
 BaseArray.typedef = TypeDef(
-    'numarray',
-    __new__ = interp2app(descr_new_array),
-
+    'ndarray',
+    __module__ = "numpypy",
+    __new__ = interp2app(BaseArray.descr__new__.im_func),
 
     __len__ = interp2app(BaseArray.descr_len),
     __getitem__ = interp2app(BaseArray.descr_getitem),
@@ -1159,11 +1258,15 @@
 
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
+    __debug_repr__ = interp2app(BaseArray.descr_debug_repr),
 
     dtype = GetSetProperty(BaseArray.descr_get_dtype),
     shape = GetSetProperty(BaseArray.descr_get_shape),
     size = GetSetProperty(BaseArray.descr_get_size),
 
+    T = GetSetProperty(BaseArray.descr_get_transpose),
+    flat = GetSetProperty(BaseArray.descr_get_flatiter),
+
     mean = interp2app(BaseArray.descr_mean),
     sum = interp2app(BaseArray.descr_sum),
     prod = interp2app(BaseArray.descr_prod),
@@ -1177,3 +1280,54 @@
 
     copy = interp2app(BaseArray.descr_copy),
 )
+
+
+class W_FlatIterator(ViewArray):
+    signature = signature.BaseSignature()
+
+    @jit.unroll_safe
+    def __init__(self, arr):
+        size = 1
+        for sh in arr.shape:
+            size *= sh
+        new_sig = signature.Signature.find_sig([
+            W_FlatIterator.signature, arr.signature
+        ])
+        ViewArray.__init__(self, arr, new_sig, [arr.strides[-1]],
+                           [arr.backstrides[-1]], [size])
+        self.shapelen = len(arr.shape)
+        self.arr = arr
+        self.iter = self.start_iter()
+
+    def start_iter(self, res_shape=None):
+        if res_shape is not None and res_shape != self.shape:
+            return BroadcastIterator(self, res_shape)
+        return OneDimIterator(self.arr.start, self.strides[0],
+                              self.shape[0])
+
+    def find_dtype(self):
+        return self.arr.find_dtype()
+
+    def find_size(self):
+        return self.shape[0]
+
+    def descr_next(self, space):
+        if self.iter.done():
+            raise OperationError(space.w_StopIteration, space.w_None)
+        result = self.eval(self.iter)
+        self.iter = self.iter.next(self.shapelen)
+        return result
+
+    def descr_iter(self):
+        return self
+
+    def debug_repr(self):
+        return 'FlatIter(%s)' % self.arr.debug_repr()
+
+
+W_FlatIterator.typedef = TypeDef(
+    'flatiter',
+    next = interp2app(W_FlatIterator.descr_next),
+    __iter__ = interp2app(W_FlatIterator.descr_iter),
+)
+W_FlatIterator.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,6 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.rlib.rstruct.runpack import runpack
 from pypy.rpython.lltypesystem import lltype, rffi
 
@@ -9,7 +9,7 @@
 
 @unwrap_spec(s=str)
 def fromstring(space, s):
-    from pypy.module.micronumpy.interp_numarray import NDimArray
+    from pypy.module.micronumpy.interp_numarray import W_NDimArray
     length = len(s)
 
     if length % FLOAT_SIZE == 0:
@@ -18,8 +18,8 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string length %d not divisable by %d" % (length, FLOAT_SIZE)))
 
-    dtype = space.fromcache(W_Float64Dtype)
-    a = NDimArray(number, [number], dtype=dtype)
+    dtype = get_dtype_cache(space).w_float64dtype
+    a = W_NDimArray(number, [number], dtype=dtype)
 
     start = 0
     end = FLOAT_SIZE
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
@@ -2,7 +2,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_dtype, signature
+from pypy.module.micronumpy import interp_boxes, interp_dtype, signature, types
 from pypy.rlib import jit
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
@@ -15,6 +15,7 @@
 
 class W_Ufunc(Wrappable):
     _attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
+    _immutable_fields_ = ["promote_to_float", "promote_bools"]
 
     def __init__(self, name, promote_to_float, promote_bools, identity):
         self.name = name
@@ -29,7 +30,7 @@
     def descr_get_identity(self, space):
         if self.identity is None:
             return space.w_None
-        return self.identity.wrap(space)
+        return self.identity
 
     def descr_call(self, space, __args__):
         if __args__.keywords or len(__args__.arguments_w) < self.argcount:
@@ -80,8 +81,7 @@
         new_sig = signature.Signature.find_sig([
             self.reduce_signature, obj.signature
         ])
-        return self.reduce_loop(new_sig, shapelen, start, value, obj,
-                           dtype).wrap(space)
+        return self.reduce_loop(new_sig, shapelen, start, value, obj, dtype)
 
     def reduce_loop(self, signature, shapelen, i, value, obj, dtype):
         while not i.done():
@@ -115,7 +115,7 @@
             promote_bools=self.promote_bools,
         )
         if isinstance(w_obj, Scalar):
-            return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
+            return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
 
         new_sig = signature.Signature.find_sig([self.signature, w_obj.signature])
         w_res = Call1(new_sig, w_obj.shape, res_dtype, w_obj, w_obj.order)
@@ -124,6 +124,7 @@
 
 
 class W_Ufunc2(W_Ufunc):
+    _immutable_fields_ = ["comparison_func", "func"]
     argcount = 2
 
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
@@ -148,14 +149,14 @@
             promote_bools=self.promote_bools,
         )
         if self.comparison_func:
-            res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+            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 self.func(calc_dtype,
                 w_lhs.value.convert_to(calc_dtype),
                 w_rhs.value.convert_to(calc_dtype)
-            ).wrap(space)
+            )
 
         new_sig = signature.Signature.find_sig([
             self.signature, w_lhs.signature, w_rhs.signature
@@ -169,7 +170,7 @@
 
 
 W_Ufunc.typedef = TypeDef("ufunc",
-    __module__ = "numpy",
+    __module__ = "numpypy",
 
     __call__ = interp2app(W_Ufunc.descr_call),
     __repr__ = interp2app(W_Ufunc.descr_repr),
@@ -187,7 +188,7 @@
         dt1, dt2 = dt2, dt1
     # Some operations promote op(bool, bool) to return int8, rather than bool
     if promote_bools and (dt1.kind == dt2.kind == interp_dtype.BOOLLTR):
-        return space.fromcache(interp_dtype.W_Int8Dtype)
+        return interp_dtype.get_dtype_cache(space).w_int8dtype
     if promote_to_float:
         return find_unaryop_result_dtype(space, dt2, promote_to_float=True)
     # If they're the same kind, choose the greater one.
@@ -197,14 +198,14 @@
     # Everything promotes to float, and bool promotes to everything.
     if dt2.kind == interp_dtype.FLOATINGLTR or dt1.kind == interp_dtype.BOOLLTR:
         # Float32 + 8-bit int = Float64
-        if dt2.num == 11 and dt1.num_bytes >= 4:
-            return space.fromcache(interp_dtype.W_Float64Dtype)
+        if dt2.num == 11 and dt1.itemtype.get_element_size() >= 4:
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         return dt2
 
     # for now this means mixing signed and unsigned
     if dt2.kind == interp_dtype.SIGNEDLTR:
         # if dt2 has a greater number of bytes, then just go with it
-        if dt1.num_bytes < dt2.num_bytes:
+        if dt1.itemtype.get_element_size() < dt2.itemtype.get_element_size():
             return dt2
         # we need to promote both dtypes
         dtypenum = dt2.num + 2
@@ -214,10 +215,11 @@
         # UInt64 + signed = Float64
         if dt2.num == 10:
             dtypenum += 1
-    newdtype = interp_dtype.ALL_DTYPES[dtypenum]
+    newdtype = interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
 
-    if newdtype.num_bytes > dt2.num_bytes or newdtype.kind == interp_dtype.FLOATINGLTR:
-        return space.fromcache(newdtype)
+    if (newdtype.itemtype.get_element_size() > dt2.itemtype.get_element_size() or
+        newdtype.kind == interp_dtype.FLOATINGLTR):
+        return newdtype
     else:
         # we only promoted to long on 32-bit or to longlong on 64-bit
         # this is really for dealing with the Long and Ulong dtypes
@@ -225,35 +227,42 @@
             dtypenum += 2
         else:
             dtypenum += 3
-        return space.fromcache(interp_dtype.ALL_DTYPES[dtypenum])
+        return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
 
 def find_unaryop_result_dtype(space, dt, promote_to_float=False,
     promote_bools=False, promote_to_largest=False):
     if promote_bools and (dt.kind == interp_dtype.BOOLLTR):
-        return space.fromcache(interp_dtype.W_Int8Dtype)
+        return interp_dtype.get_dtype_cache(space).w_int8dtype
     if promote_to_float:
         if dt.kind == interp_dtype.FLOATINGLTR:
             return dt
         if dt.num >= 5:
-            return space.fromcache(interp_dtype.W_Float64Dtype)
-        for bytes, dtype in interp_dtype.dtypes_by_num_bytes:
-            if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes > dt.num_bytes:
-                return space.fromcache(dtype)
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
+        for bytes, dtype in interp_dtype.get_dtype_cache(space).dtypes_by_num_bytes:
+            if (dtype.kind == interp_dtype.FLOATINGLTR and
+                dtype.itemtype.get_element_size() > dt.itemtype.get_element_size()):
+                return dtype
     if promote_to_largest:
         if dt.kind == interp_dtype.BOOLLTR or dt.kind == interp_dtype.SIGNEDLTR:
-            return space.fromcache(interp_dtype.W_Int64Dtype)
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         elif dt.kind == interp_dtype.FLOATINGLTR:
-            return space.fromcache(interp_dtype.W_Float64Dtype)
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         elif dt.kind == interp_dtype.UNSIGNEDLTR:
-            return space.fromcache(interp_dtype.W_UInt64Dtype)
+            return interp_dtype.get_dtype_cache(space).w_uint64dtype
         else:
             assert False
     return dt
 
 def find_dtype_for_scalar(space, w_obj, current_guess=None):
-    bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
-    long_dtype = space.fromcache(interp_dtype.W_LongDtype)
-    int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
+    bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+    long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
+    int64_dtype = interp_dtype.get_dtype_cache(space).w_int64dtype
+
+    if isinstance(w_obj, interp_boxes.W_GenericBox):
+        dtype = w_obj.get_dtype(space)
+        if current_guess is None:
+            return dtype
+        return find_binop_result_dtype(space, dtype, current_guess)
 
     if space.isinstance_w(w_obj, space.w_bool):
         if current_guess is None or current_guess is bool_dtype:
@@ -269,20 +278,19 @@
             current_guess is long_dtype or current_guess is int64_dtype):
             return int64_dtype
         return current_guess
-    return space.fromcache(interp_dtype.W_Float64Dtype)
+    return interp_dtype.get_dtype_cache(space).w_float64dtype
 
 
 def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
     if argcount == 1:
         def impl(res_dtype, value):
-            return getattr(res_dtype, op_name)(value)
+            return getattr(res_dtype.itemtype, op_name)(value)
     elif argcount == 2:
+        dtype_cache = interp_dtype.get_dtype_cache(space)
         def impl(res_dtype, lvalue, rvalue):
-            res = getattr(res_dtype, op_name)(lvalue, rvalue)
+            res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
             if comparison_func:
-                booldtype = space.fromcache(interp_dtype.W_BoolDtype)
-                assert isinstance(booldtype, interp_dtype.W_BoolDtype)
-                res = booldtype.box(res)
+                return dtype_cache.w_booldtype.box(res)
             return res
     return func_with_new_name(impl, ufunc_name)
 
@@ -319,6 +327,8 @@
             ("floor", "floor", 1, {"promote_to_float": True}),
             ("exp", "exp", 1, {"promote_to_float": True}),
 
+            ('sqrt', 'sqrt', 1, {'promote_to_float': True}),
+
             ("sin", "sin", 1, {"promote_to_float": True}),
             ("cos", "cos", 1, {"promote_to_float": True}),
             ("tan", "tan", 1, {"promote_to_float": True}),
@@ -336,7 +346,7 @@
 
         identity = extra_kwargs.get("identity")
         if identity is not None:
-            identity = space.fromcache(interp_dtype.W_LongDtype).adapt_val(identity)
+            identity = interp_dtype.get_dtype_cache(space).w_longdtype.box(identity)
         extra_kwargs["identity"] = identity
 
         func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
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
@@ -40,13 +40,15 @@
         return Signature._known_sigs.setdefault(components, Signature(components))
 
 class Call1(BaseSignature):
-    _immutable_fields_ = ["func"]
+    _immutable_fields_ = ["func", "name"]
 
     def __init__(self, func):
         self.func = func
+        self.name = func.func_name
 
 class Call2(BaseSignature):
-    _immutable_fields_ = ["func"]
+    _immutable_fields_ = ["func", "name"]
 
     def __init__(self, func):
         self.func = func
+        self.name = func.func_name
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -1,6 +1,6 @@
 from pypy.conftest import gettestobjspace
-from pypy.module.micronumpy import interp_dtype
-from pypy.module.micronumpy.interp_numarray import NDimArray, Scalar
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, Scalar
 from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype,
         find_unaryop_result_dtype)
 
@@ -11,9 +11,10 @@
 
 class TestSignature(object):
     def test_binop_signature(self, space):
-        float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+        float64_dtype = get_dtype_cache(space).w_float64dtype
+        bool_dtype = get_dtype_cache(space).w_booldtype
 
-        ar = NDimArray(10, [10], dtype=float64_dtype)
+        ar = W_NDimArray(10, [10], dtype=float64_dtype)
         v1 = ar.descr_add(space, ar)
         v2 = ar.descr_add(space, Scalar(float64_dtype, 2.0))
         assert v1.signature is not v2.signature
@@ -22,7 +23,7 @@
         v4 = ar.descr_add(space, ar)
         assert v1.signature is v4.signature
 
-        bool_ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_BoolDtype))
+        bool_ar = W_NDimArray(10, [10], dtype=bool_dtype)
         v5 = ar.descr_add(space, bool_ar)
         assert v5.signature is not v1.signature
         assert v5.signature is not v2.signature
@@ -30,7 +31,9 @@
         assert v5.signature is v6.signature
 
     def test_slice_signature(self, space):
-        ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_Float64Dtype))
+        float64_dtype = get_dtype_cache(space).w_float64dtype
+
+        ar = W_NDimArray(10, [10], dtype=float64_dtype)
         v1 = ar.descr_getitem(space, space.wrap(slice(1, 3, 1)))
         v2 = ar.descr_getitem(space, space.wrap(slice(4, 6, 1)))
         assert v1.signature is v2.signature
@@ -41,10 +44,10 @@
 
 class TestUfuncCoerscion(object):
     def test_binops(self, space):
-        bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
-        int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
-        int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
-        float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+        bool_dtype = get_dtype_cache(space).w_booldtype
+        int8_dtype = get_dtype_cache(space).w_int8dtype
+        int32_dtype = get_dtype_cache(space).w_int32dtype
+        float64_dtype = get_dtype_cache(space).w_float64dtype
 
         # Basic pairing
         assert find_binop_result_dtype(space, bool_dtype, bool_dtype) is bool_dtype
@@ -62,19 +65,19 @@
         assert find_binop_result_dtype(space, bool_dtype, float64_dtype, promote_to_float=True) is float64_dtype
 
     def test_unaryops(self, space):
-        bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
-        int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
-        uint8_dtype = space.fromcache(interp_dtype.W_UInt8Dtype)
-        int16_dtype = space.fromcache(interp_dtype.W_Int16Dtype)
-        uint16_dtype = space.fromcache(interp_dtype.W_UInt16Dtype)
-        int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
-        uint32_dtype = space.fromcache(interp_dtype.W_UInt32Dtype)
-        long_dtype = space.fromcache(interp_dtype.W_LongDtype)
-        ulong_dtype = space.fromcache(interp_dtype.W_ULongDtype)
-        int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
-        uint64_dtype = space.fromcache(interp_dtype.W_UInt64Dtype)
-        float32_dtype = space.fromcache(interp_dtype.W_Float32Dtype)
-        float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+        bool_dtype = get_dtype_cache(space).w_booldtype
+        int8_dtype = get_dtype_cache(space).w_int8dtype
+        uint8_dtype = get_dtype_cache(space).w_uint8dtype
+        int16_dtype = get_dtype_cache(space).w_int16dtype
+        uint16_dtype = get_dtype_cache(space).w_uint16dtype
+        int32_dtype = get_dtype_cache(space).w_int32dtype
+        uint32_dtype = get_dtype_cache(space).w_uint32dtype
+        long_dtype = get_dtype_cache(space).w_longdtype
+        ulong_dtype = get_dtype_cache(space).w_ulongdtype
+        int64_dtype = get_dtype_cache(space).w_int64dtype
+        uint64_dtype = get_dtype_cache(space).w_uint64dtype
+        float32_dtype = get_dtype_cache(space).w_float32dtype
+        float64_dtype = get_dtype_cache(space).w_float64dtype
 
         # Normal rules, everything returns itself
         assert find_unaryop_result_dtype(space, bool_dtype) is bool_dtype
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -1,6 +1,9 @@
+import py
 
-import py
-from pypy.module.micronumpy.compile import *
+from pypy.module.micronumpy.compile import (numpy_compile, Assignment,
+    ArrayConstant, FloatConstant, Operator, Variable, RangeConstant, Execute,
+    FunctionCall, FakeSpace)
+
 
 class TestCompiler(object):
     def compile(self, code):
@@ -106,7 +109,7 @@
         c -> 3
         """
         interp = self.run(code)
-        assert interp.results[-1].value.val == 9
+        assert interp.results[-1].value == 9
 
     def test_array_getitem(self):
         code = """
@@ -115,7 +118,7 @@
         a + b -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 3 + 6
+        assert interp.results[0].value == 3 + 6
 
     def test_range_getitem(self):
         code = """
@@ -123,7 +126,7 @@
         r -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
 
     def test_sum(self):
         code = """
@@ -132,7 +135,7 @@
         r
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 15
+        assert interp.results[0].value.value == 15
 
     def test_array_write(self):
         code = """
@@ -141,7 +144,7 @@
         a -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 15
+        assert interp.results[0].value == 15
 
     def test_min(self):
         interp = self.run("""
@@ -150,7 +153,7 @@
         b = a + a
         min(b)
         """)
-        assert interp.results[0].value.val == -24
+        assert interp.results[0].value.value == -24
 
     def test_max(self):
         interp = self.run("""
@@ -159,7 +162,7 @@
         b = a + a
         max(b)
         """)
-        assert interp.results[0].value.val == 256
+        assert interp.results[0].value.value == 256
 
     def test_slice(self):
         interp = self.run("""
@@ -167,7 +170,7 @@
         b = a -> :
         b -> 3
         """)
-        assert interp.results[0].value.val == 4
+        assert interp.results[0].value == 4
 
     def test_slice_step(self):
         interp = self.run("""
@@ -175,14 +178,35 @@
         b = a -> ::2
         b -> 3
         """)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
+
+    def test_setslice(self):
+        interp = self.run("""
+        a = |30|
+        b = |10|
+        b[1] = 5
+        a[::3] = b
+        a -> 3
+        """)
+        assert interp.results[0].value == 5
+
+
+    def test_slice2(self):
+        interp = self.run("""
+        a = |30|
+        s1 = a -> 0:20:2
+        s2 = a -> 0:30:3
+        b = s1 + s2
+        b -> 3
+        """)
+        assert interp.results[0].value == 15
 
     def test_multidim_getitem(self):
         interp = self.run("""
         a = [[1,2]]
         a -> 0 -> 1
         """)
-        assert interp.results[0].value.val == 2
+        assert interp.results[0].value == 2
 
     def test_multidim_getitem_2(self):
         interp = self.run("""
@@ -190,4 +214,24 @@
         b = a + a
         b -> 1 -> 1
         """)
-        assert interp.results[0].value.val == 8
+        assert interp.results[0].value == 8
+
+    def test_set_slice(self):
+        interp = self.run("""
+        a = |30|
+        b = |30|
+        b[:] = a + a
+        b -> 3
+        """)
+        assert interp.results[0].value == 6
+
+    def test_set_slice2(self):
+        interp = self.run("""
+        a = |30|
+        b = |10|
+        b[1] = 5.5
+        c = b + b
+        a[0:30:3] = c
+        a -> 3
+        """)
+        assert interp.results[0].value == 11
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -30,7 +30,7 @@
     def test_repr_str(self):
         from numpypy import dtype
 
-        assert repr(dtype) == "<type 'numpy.dtype'>"
+        assert repr(dtype) == "<type 'numpypy.dtype'>"
         d = dtype('?')
         assert repr(d) == "dtype('bool')"
         assert str(d) == "bool"
@@ -44,13 +44,13 @@
             assert a[i] is True_
 
     def test_copy_array_with_dtype(self):
-        from numpypy import array, False_, True_
+        from numpypy import array, False_, True_, int64
 
         a = array([0, 1, 2, 3], dtype=long)
         # int on 64-bit, long in 32-bit
-        assert isinstance(a[0], (int, long))
+        assert isinstance(a[0], int64)
         b = a.copy()
-        assert isinstance(b[0], (int, long))
+        assert isinstance(b[0], int64)
 
         a = array([0, 1, 2, 3], dtype=bool)
         assert a[0] is False_
@@ -72,17 +72,17 @@
             assert a[i] is True_
 
     def test_zeros_long(self):
-        from numpypy import zeros
+        from numpypy import zeros, int64
         a = zeros(10, dtype=long)
         for i in range(10):
-            assert isinstance(a[i], (int, long))
+            assert isinstance(a[i], int64)
             assert a[1] == 0
 
     def test_ones_long(self):
-        from numpypy import ones
+        from numpypy import ones, int64
         a = ones(10, dtype=long)
         for i in range(10):
-            assert isinstance(a[i], (int, long))
+            assert isinstance(a[i], int64)
             assert a[1] == 1
 
     def test_overflow(self):
@@ -165,3 +165,99 @@
 
         # You can't subclass dtype
         raises(TypeError, type, "Foo", (dtype,), {})
+
+class AppTestTypes(BaseNumpyAppTest):
+    def test_abstract_types(self):
+        import numpypy as numpy
+        raises(TypeError, numpy.generic, 0)
+        raises(TypeError, numpy.number, 0)
+        raises(TypeError, numpy.integer, 0)
+        exc = raises(TypeError, numpy.signedinteger, 0)
+        assert str(exc.value) == "cannot create 'numpypy.signedinteger' instances"
+
+        raises(TypeError, numpy.floating, 0)
+        raises(TypeError, numpy.inexact, 0)
+
+    def test_bool(self):
+        import numpypy as numpy
+
+        assert numpy.bool_.mro() == [numpy.bool_, numpy.generic, object]
+        assert numpy.bool_(3) is numpy.True_
+        assert numpy.bool_("") is numpy.False_
+        assert type(numpy.True_) is type(numpy.False_) is numpy.bool_
+
+        class X(numpy.bool_):
+            pass
+
+        assert type(X(True)) is numpy.bool_
+        assert X(True) is numpy.True_
+
+    def test_int8(self):
+        import numpypy as numpy
+
+        assert numpy.int8.mro() == [numpy.int8, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+        a = numpy.array([1, 2, 3], numpy.int8)
+        assert type(a[1]) is numpy.int8
+        assert numpy.dtype("int8").type is numpy.int8
+
+        x = numpy.int8(128)
+        assert x == -128
+        assert x != 128
+        assert type(x) is numpy.int8
+        assert repr(x) == "-128"
+
+        assert type(int(x)) is int
+        assert int(x) == -128
+
+    def test_int16(self):
+        import numpypy as numpy
+
+        x = numpy.int16(3)
+        assert x == 3
+
+    def test_int32(self):
+        import numpypy as numpy
+
+        x = numpy.int32(23)
+        assert x == 23
+
+    def test_int_(self):
+        import numpypy as numpy
+
+        assert numpy.int_ is numpy.dtype(int).type
+        assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+
+    def test_int64(self):
+        import sys
+        import numpypy as numpy
+
+        if sys.maxint == 2 ** 63 -1:
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+        else:
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+        assert numpy.dtype(numpy.int64).type is numpy.int64
+        assert numpy.int64(3) == 3
+
+    def test_float64(self):
+        import numpypy as numpy
+
+        assert numpy.float64.mro() == [numpy.float64, numpy.floating, numpy.inexact, numpy.number, numpy.generic, float, object]
+
+        a = numpy.array([1, 2, 3], numpy.float64)
+        assert type(a[1]) is numpy.float64
+        assert numpy.dtype(float).type is numpy.float64
+
+        assert numpy.float64(2.0) == 2.0
+
+    def test_subclass_type(self):
+        import numpypy as numpy
+
+        class X(numpy.float64):
+            def m(self):
+                return self + 2
+
+        b = X(10)
+        assert type(b) is X
+        assert b.m() == 12
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
@@ -1,16 +1,19 @@
 
 import py
 from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
-from pypy.module.micronumpy.interp_numarray import NDimArray, shape_agreement
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, shape_agreement
 from pypy.module.micronumpy import signature
 from pypy.interpreter.error import OperationError
 from pypy.conftest import gettestobjspace
 
+
 class MockDtype(object):
     signature = signature.BaseSignature()
+
     def malloc(self, size):
         return None
 
+
 class TestNumArrayDirect(object):
     def newslice(self, *args):
         return self.space.newslice(*[self.space.wrap(arg) for arg in args])
@@ -25,18 +28,18 @@
         return self.space.newtuple(args_w)
 
     def test_strides_f(self):
-        a = NDimArray(100, [10, 5, 3], MockDtype(), 'F')
+        a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'F')
         assert a.strides == [1, 10, 50]
         assert a.backstrides == [9, 40, 100]
 
     def test_strides_c(self):
-        a = NDimArray(100, [10, 5, 3], MockDtype(), 'C')
+        a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'C')
         assert a.strides == [15, 3, 1]
         assert a.backstrides == [135, 12, 2]
 
     def test_create_slice_f(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
         s = a.create_slice(space, [(3, 0, 0, 1)])
         assert s.start == 3
         assert s.strides == [10, 50]
@@ -55,7 +58,7 @@
 
     def test_create_slice_c(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
         s = a.create_slice(space, [(3, 0, 0, 1)])
         assert s.start == 45
         assert s.strides == [3, 1]
@@ -75,7 +78,7 @@
 
     def test_slice_of_slice_f(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
         s = a.create_slice(space, [(5, 0, 0, 1)])
         assert s.start == 5
         s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -93,7 +96,7 @@
 
     def test_slice_of_slice_c(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
         s = a.create_slice(space, [(5, 0, 0, 1)])
         assert s.start == 15 * 5
         s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -111,7 +114,7 @@
 
     def test_negative_step_f(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
         s = a.create_slice(space, [(9, -1, -2, 5)])
         assert s.start == 9
         assert s.strides == [-2, 10, 50]
@@ -119,14 +122,14 @@
 
     def test_negative_step_c(self):
         space = self.space
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
         s = a.create_slice(space, [(9, -1, -2, 5)])
         assert s.start == 135
         assert s.strides == [-30, 3, 1]
         assert s.backstrides == [-120, 12, 2]
 
     def test_index_of_single_item_f(self):
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
         r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
         assert r == 1 + 2 * 10 + 2 * 50
         s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -136,7 +139,7 @@
         assert r == a._index_of_single_item(self.space, self.newtuple(1, 2, 1))
 
     def test_index_of_single_item_c(self):
-        a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+        a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
         r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
         assert r == 1 * 3 * 5 + 2 * 3 + 2
         s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -150,10 +153,28 @@
         assert shape_agreement(self.space, [1, 2, 3], [1, 2, 3]) == [1, 2, 3]
         py.test.raises(OperationError, shape_agreement, self.space, [2], [3])
         assert shape_agreement(self.space, [4, 4], []) == [4, 4]
-        assert shape_agreement(self.space, [8, 1, 6, 1], [7, 1, 5]) == [8, 7, 6, 5]
-        assert shape_agreement(self.space, [5, 2], [4, 3, 5, 2]) == [4, 3, 5, 2]
+        assert shape_agreement(self.space,
+                [8, 1, 6, 1], [7, 1, 5]) == [8, 7, 6, 5]
+        assert shape_agreement(self.space,
+                [5, 2], [4, 3, 5, 2]) == [4, 3, 5, 2]
+
 
 class AppTestNumArray(BaseNumpyAppTest):
+    def test_ndarray(self):
+        from numpypy import ndarray, array, dtype
+
+        assert type(ndarray) is type
+        assert type(array) is not type
+        a = ndarray((2, 3))
+        assert a.shape == (2, 3)
+        assert a.dtype == dtype(float)
+
+        raises(TypeError, ndarray, [[1], [2], [3]])
+
+        a = ndarray(3, dtype=int)
+        assert a.shape == (3,)
+        assert a.dtype is dtype(int)
+
     def test_type(self):
         from numpypy import array
         ar = array(range(5))
@@ -170,8 +191,7 @@
 
     def test_size(self):
         from numpypy import array
-        # XXX fixed on multidim branch
-        #assert array(3).size == 1
+        assert array(3).size == 1
         a = array([1, 2, 3])
         assert a.size == 3
         assert (a + a).size == 3
@@ -204,13 +224,13 @@
         a[3] = 22
         assert b[3] == 3
 
+        a = array(1)
+        assert a.copy() == a
+
     def test_iterator_init(self):
         from numpypy import array
         a = array(range(5))
         assert a[3] == 3
-        a = array(1)
-        assert a[0] == 1
-        assert a.shape == ()
 
     def test_getitem(self):
         from numpypy import array
@@ -258,7 +278,7 @@
         assert a[1] == 0.
         assert a[3] == 1.
         b[::-1] = b
-        assert b[0] == 1.
+        assert b[0] == 0.
         assert b[1] == 0.
 
     def test_setslice_of_slice_array(self):
@@ -296,9 +316,13 @@
         assert a[3] == 0.
 
     def test_scalar(self):
-        from numpypy import array
+        from numpypy import array, dtype
         a = array(3)
-        assert a[0] == 3
+        #assert a[0] == 3
+        raises(IndexError, "a[0]")
+        assert a.size == 1
+        assert a.shape == ()
+        assert a.dtype is dtype(int)
 
     def test_len(self):
         from numpypy import array
@@ -350,11 +374,11 @@
             assert r[i] == i + 3
 
     def test_add_list(self):
-        from numpypy import array
+        from numpypy import array, ndarray
         a = array(range(5))
         b = list(reversed(range(5)))
         c = a + b
-        assert isinstance(c, array)
+        assert isinstance(c, ndarray)
         for i in range(5):
             assert c[i] == 4
 
@@ -455,9 +479,11 @@
         a = array(range(5), float)
         b = a ** a
         for i in range(5):
-            print b[i], i ** i
             assert b[i] == i ** i
 
+        a = array(range(5))
+        assert (a ** 2 == a * a).all()
+
     def test_pow_other(self):
         from numpypy import array
         a = array(range(5), float)
@@ -681,12 +707,14 @@
         assert c.any() == False
 
     def test_dot(self):
-        from numpypy import array
+        from numpypy import array, dot
         a = array(range(5))
         assert a.dot(a) == 30.0
 
         a = array(range(5))
         assert a.dot(range(5)) == 30
+        assert dot(range(5), range(5)) == 30
+        assert (dot(5, [1, 2, 3]) == [5, 10, 15]).all()
 
     def test_dot_constant(self):
         from numpypy import array
@@ -696,7 +724,7 @@
             assert b[i] == 2.5 * a[i]
 
     def test_dtype_guessing(self):
-        from numpypy import array, dtype
+        from numpypy import array, dtype, float64, int8, bool_
 
         assert array([True]).dtype is dtype(bool)
         assert array([True, False]).dtype is dtype(bool)
@@ -706,6 +734,10 @@
         assert array([1.2, True]).dtype is dtype(float)
         assert array([1.2, 5]).dtype is dtype(float)
         assert array([]).dtype is dtype(float)
+        assert array([float64(2)]).dtype is dtype(float)
+        assert array([int8(3)]).dtype is dtype("int8")
+        assert array([bool_(True)]).dtype is dtype(bool)
+        assert array([bool_(True), 3.0]).dtype is dtype(float)
 
     def test_comparison(self):
         import operator
@@ -737,6 +769,29 @@
         assert bool(array([1]))
         assert not bool(array([0]))
 
+    def test_slice_assignment(self):
+        from numpypy import array
+        a = array(range(5))
+        a[::-1] = a
+        assert (a == [0, 1, 2, 1, 0]).all()
+        # but we force intermediates
+        a = array(range(5))
+        a[::-1] = a + a
+        assert (a == [8, 6, 4, 2, 0]).all()
+
+    def test_debug_repr(self):
+        from numpypy import zeros, sin
+        a = zeros(1)
+        assert a.__debug_repr__() == 'Array'
+        assert (a + a).__debug_repr__() == 'Call2(add, Array, Array)'
+        assert (a[::2]).__debug_repr__() == 'Slice(Array)'
+        assert (a + 2).__debug_repr__() == 'Call2(add, Array, Scalar)'
+        assert (a + a.flat).__debug_repr__() == 'Call2(add, Array, FlatIter(Array))'
+        assert sin(a).__debug_repr__() == 'Call1(sin, Array)'
+        b = a + a
+        b[0] = 3
+        assert b.__debug_repr__() == 'Call2(add, forced=Array)'
+
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
         import numpypy
@@ -829,7 +884,8 @@
     def test_ufunc(self):
         from numpypy import array
         a = array([[1, 2], [3, 4], [5, 6]])
-        assert ((a + a) == array([[1 + 1, 2 + 2], [3 + 3, 4 + 4], [5 + 5, 6 + 6]])).all()
+        assert ((a + a) == \
+            array([[1 + 1, 2 + 2], [3 + 3, 4 + 4], [5 + 5, 6 + 6]])).all()
 
     def test_getitem_add(self):
         from numpypy import array
@@ -844,7 +900,8 @@
 
     def test_getitem_3(self):
         from numpypy import array
-        a = array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14]])
+        a = array([[1, 2], [3, 4], [5, 6], [7, 8],
+                   [9, 10], [11, 12], [13, 14]])
         b = a[::2]
         print a
         print b
@@ -877,11 +934,12 @@
         b = array(((10, 11, 12), (20, 21, 22), (30, 31, 32)))
         c = ((a + b) == [b, b, b])
         assert c.all()
-        a = array((((10,11,12), ), ((20, 21, 22), ), ((30,31,32), )))
+        a = array((((10, 11, 12), ), ((20, 21, 22), ), ((30, 31, 32), )))
         assert(a.shape == (3, 1, 3))
         d = zeros((3, 3))
         c = ((a + d) == [b, b, b])
-        c = ((a + d) == array([[[10., 11., 12.]]*3, [[20.,21.,22.]]*3, [[30.,31.,32.]]*3]))
+        c = ((a + d) == array([[[10., 11., 12.]] * 3,
+                               [[20., 21., 22.]] * 3, [[30., 31., 32.]] * 3]))
         assert c.all()
 
     def test_broadcast_scalar(self):
@@ -906,14 +964,15 @@
         from numpypy import array
         a = array([[1, 2], [3, 4], [5, 6]])
         assert a.argmax() == 5
-        assert a[:2,].argmax() == 3
+        assert a[:2, ].argmax() == 3
 
     def test_broadcast_wrong_shapes(self):
         from numpypy import zeros
         a = zeros((4, 3, 2))
         b = zeros((4, 2))
         exc = raises(ValueError, lambda: a + b)
-        assert str(exc.value) == "operands could not be broadcast together with shapes (4,3,2) (4,2)"
+        assert str(exc.value) == "operands could not be broadcast" \
+            " together with shapes (4,3,2) (4,2)"
 
     def test_reduce(self):
         from numpypy import array
@@ -923,10 +982,55 @@
         c = b + b
         assert c.sum() == (6 + 8 + 10 + 12) * 2
 
-class AppTestSupport(object):
+    def test_transpose(self):
+        from numpypy import array
+        a = array(((range(3), range(3, 6)),
+                   (range(6, 9), range(9, 12)),
+                   (range(12, 15), range(15, 18)),
+                   (range(18, 21), range(21, 24))))
+        assert a.shape == (4, 2, 3)
+        b = a.T
+        assert b.shape == (3, 2, 4)
+        assert(b[0, :, 0] == [0, 3]).all()
+        b[:, 0, 0] = 1000
+        assert(a[0, 0, :] == [1000, 1000, 1000]).all()
+        a = array(range(5))
+        b = a.T
+        assert(b == range(5)).all()
+        a = array((range(10), range(20, 30)))
+        b = a.T
+        assert(b[:, 0] == a[0, :]).all()
+
+    def test_flatiter(self):
+        from numpypy import array, flatiter
+        a = array([[10, 30], [40, 60]])
+        f_iter = a.flat
+        assert f_iter.next() == 10
+        assert f_iter.next() == 30
+        assert f_iter.next() == 40
+        assert f_iter.next() == 60
+        raises(StopIteration, "f_iter.next()")
+        raises(TypeError, "flatiter()")
+        s = 0
+        for k in a.flat:
+            s += k
+        assert s == 140
+
+    def test_flatiter_array_conv(self):
+        from numpypy import array, dot
+        a = array([1, 2, 3])
+        assert dot(a.flat, a.flat) == 14
+
+    def test_slice_copy(self):
+        from numpypy import zeros
+        a = zeros((10, 10))
+        b = a[0].copy()
+        assert (b == zeros(10)).all()
+
+class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
         import struct
-        cls.space = gettestobjspace(usemodules=('micronumpy',))
+        BaseNumpyAppTest.setup_class.im_func(cls)
         cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
 
     def test_fromstring(self):
@@ -936,6 +1040,7 @@
             assert a[i] == i + 1
         raises(ValueError, fromstring, "abc")
 
+
 class AppTestRepr(BaseNumpyAppTest):
     def test_repr(self):
         from numpypy import array, zeros
@@ -1008,7 +1113,9 @@
         assert str(a) == "3"
 
         a = zeros((400, 400), dtype=int)
-        assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
+        assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n" \
+           " [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n" \
+           " [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
         a = zeros((2, 2, 2))
         r = str(a)
         assert r == '[[[0.0 0.0]\n  [0.0 0.0]]\n\n [[0.0 0.0]\n  [0.0 0.0]]]'
@@ -1026,3 +1133,25 @@
         assert str(b) == "[7 8 9]"
         b = a[2:1, ]
         assert str(b) == "[]"
+
+
+class AppTestRanges(BaseNumpyAppTest):
+    def test_arange(self):
+        from numpypy import arange, array, dtype
+        a = arange(3)
+        assert (a == [0, 1, 2]).all()
+        assert a.dtype is dtype(int)
+        a = arange(3.0)
+        assert (a == [0., 1., 2.]).all()
+        assert a.dtype is dtype(float)
+        a = arange(3, 7)
+        assert (a == [3, 4, 5, 6]).all()
+        assert a.dtype is dtype(int)
+        a = arange(3, 7, 2)
+        assert (a == [3, 5]).all()
+        a = arange(3, dtype=float)
+        assert (a == [0., 1., 2.]).all()
+        assert a.dtype is dtype(float)
+        a = arange(0, 0.8, 0.1)
+        assert len(a) == 8
+        assert arange(False, True, True).dtype is dtype(int)
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -8,7 +8,7 @@
 
         assert isinstance(add, ufunc)
         assert repr(add) == "<ufunc 'add'>"
-        assert repr(ufunc) == "<type 'numpy.ufunc'>"
+        assert repr(ufunc) == "<type 'numpypy.ufunc'>"
 
     def test_ufunc_attrs(self):
         from numpypy import add, multiply, sin
@@ -37,36 +37,36 @@
         assert minimum(2.0, 3.0) == 2.0
 
     def test_sequence(self):
-        from numpypy import array, negative, minimum
+        from numpypy import array, ndarray, negative, minimum
         a = array(range(3))
         b = [2.0, 1.0, 0.0]
         c = 1.0
         b_neg = negative(b)
-        assert isinstance(b_neg, array)
+        assert isinstance(b_neg, ndarray)
         for i in range(3):
             assert b_neg[i] == -b[i]
         min_a_b = minimum(a, b)
-        assert isinstance(min_a_b, array)
+        assert isinstance(min_a_b, ndarray)
         for i in range(3):
             assert min_a_b[i] == min(a[i], b[i])
         min_b_a = minimum(b, a)
-        assert isinstance(min_b_a, array)
+        assert isinstance(min_b_a, ndarray)
         for i in range(3):
             assert min_b_a[i] == min(a[i], b[i])
         min_a_c = minimum(a, c)
-        assert isinstance(min_a_c, array)
+        assert isinstance(min_a_c, ndarray)
         for i in range(3):
             assert min_a_c[i] == min(a[i], c)
         min_c_a = minimum(c, a)
-        assert isinstance(min_c_a, array)
+        assert isinstance(min_c_a, ndarray)
         for i in range(3):
             assert min_c_a[i] == min(a[i], c)
         min_b_c = minimum(b, c)
-        assert isinstance(min_b_c, array)
+        assert isinstance(min_b_c, ndarray)
         for i in range(3):
             assert min_b_c[i] == min(b[i], c)
         min_c_b = minimum(c, b)
-        assert isinstance(min_c_b, array)
+        assert isinstance(min_c_b, ndarray)
         for i in range(3):
             assert min_c_b[i] == min(b[i], c)
 
@@ -111,6 +111,8 @@
         for i in range(3):
             assert c[i] == a[i] / b[i]
 
+        assert (divide(array([-10]), array([2])) == array([-5])).all()
+
     def test_fabs(self):
         from numpypy import array, fabs
         from math import fabs as math_fabs
@@ -319,6 +321,17 @@
         for v in [1.0, -1.0]:
             assert arctanh(v) == math.copysign(float("inf"), v)
 
+    def test_sqrt(self):
+        import math
+        from numpypy import sqrt
+
+        nan, inf = float("nan"), float("inf")
+        data = [1, 2, 3, inf]
+        results = [math.sqrt(1), math.sqrt(2), math.sqrt(3), inf]
+        assert (sqrt(data) == results).all()
+        assert math.isnan(sqrt(-1))
+        assert math.isnan(sqrt(nan))
+
     def test_reduce_errors(self):
         from numpypy import sin, add
 
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
@@ -8,10 +8,11 @@
 from pypy.jit.metainterp import pyjitpl
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.jit.metainterp.warmspot import reset_stats
-from pypy.module.micronumpy import interp_ufuncs, signature
+from pypy.module.micronumpy import interp_boxes, interp_ufuncs, signature
 from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace,
     FloatObject, IntObject, BoolObject, Parser, InterpreterState)
-from pypy.module.micronumpy.interp_numarray import NDimArray, NDimSlice
+from pypy.module.micronumpy.interp_numarray import (W_NDimArray, NDimSlice,
+     BaseArray)
 from pypy.rlib.nonconst import NonConstant
 from pypy.rpython.annlowlevel import llstr, hlstr
 
@@ -47,16 +48,15 @@
         def f(i):
             interp = InterpreterState(codes[i])
             interp.run(space)
-            res = interp.results[-1]
-            w_res = res.eval(res.start_iter()).wrap(interp.space)
-            if isinstance(w_res, BoolObject):
-                return float(w_res.boolval)
-            elif isinstance(w_res, FloatObject):
-                return w_res.floatval
-            elif isinstance(w_res, IntObject):
-                return w_res.intval
-            else:
-                return -42.
+            w_res = interp.results[-1]
+            if isinstance(w_res, BaseArray):
+                w_res = w_res.eval(w_res.start_iter())
+
+            if isinstance(w_res, interp_boxes.W_Float64Box):
+                return w_res.value
+            elif isinstance(w_res, interp_boxes.W_BoolBox):
+                return float(w_res.value)
+            raise TypeError(w_res)
 
         if self.graph is None:
             interp, graph = self.meta_interp(f, [i],
@@ -78,10 +78,9 @@
 
     def test_add(self):
         result = self.run("add")
-        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
-                           'int_add': 6, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
-                           'guard_value': 1})
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1, 'jump': 1})
         assert result == 3 + 3
 
     def define_float_add():
@@ -93,10 +92,9 @@
     def test_floatadd(self):
         result = self.run("float_add")
         assert result == 3 + 3
-        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 17, 'guard_class': 11,
-                           'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 2, 'float_add': 2, 'guard_false': 2,
-                           'guard_value': 1})
+        self.check_simple_loop({"getinteriorfield_raw": 1, "float_add": 1,
+                                "setinteriorfield_raw": 1, "int_add": 2,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def define_sum():
         return """
@@ -108,9 +106,9 @@
     def test_sum(self):
         result = self.run("sum")
         assert result == 2 * sum(range(30))
-        self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'jump': 1,
-                           'getarrayitem_raw': 4, 'guard_value': 2, 'int_add': 4,
-                           'guard_isnull': 1, 'int_ge': 2, 'float_add': 4, 'guard_false': 2})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 2,
+                                "int_add": 2, "int_ge": 1, "guard_false": 1,
+                                "jump": 1})
 
     def define_prod():
         return """
@@ -125,11 +123,9 @@
         for i in range(30):
             expected *= i * 2
         assert result == expected
-        self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'int_add': 4,
-                           'float_mul': 2, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
-                           'guard_value': 2})
-
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 2,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def test_max(self):
         py.test.skip("broken, investigate")
@@ -140,9 +136,9 @@
         max(b)
         """)
         assert result == 256
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 1,
-                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 1,
+                                "int_lt": 1, "guard_true": 1, "jump": 1})
 
     def test_min(self):
         py.test.skip("broken, investigate")
@@ -153,10 +149,9 @@
         min(b)
         """)
         assert result == -24
-        self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
-                           'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
-                           'float_ne': 2})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 1,
+                                "int_lt": 1, "guard_true": 1, "jump": 1})
 
     def define_any():
         return """
@@ -169,10 +164,10 @@
     def test_any(self):
         result = self.run("any")
         assert result == 1
-        self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
-                           'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
-                           'float_ne': 2})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_ne": 1, "int_add": 2,
+                                "int_ge": 1, "jump": 1,
+                                "guard_false": 2})
 
     def define_already_forced():
         return """
@@ -189,13 +184,14 @@
         # This is the sum of the ops for both loops, however if you remove the
         # optimization then you end up with 2 float_adds, so we can still be
         # sure it was optimized correctly.
-        self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+        # XXX the comment above is wrong now.  We need preferrably a way to
+        # count the two loops separately
+        self.check_resops({'setinteriorfield_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 41,
                            'guard_class': 22, 'int_add': 8, 'float_mul': 2,
                            'guard_isnull': 2, 'jump': 2, 'int_ge': 4,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+                           'getinteriorfield_raw': 4, 'float_add': 2, 'guard_false': 4,
                            'guard_value': 2})
 
-
     def define_ufunc():
         return """
         a = |30|
@@ -207,11 +203,9 @@
     def test_ufunc(self):
         result = self.run("ufunc")
         assert result == -6
-        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 24, 'guard_class': 14,
-                           'int_add': 6, 'float_neg': 2, 'guard_isnull': 2, 'jump': 1,
-                           'int_ge': 2, 'getarrayitem_raw': 4, 'float_add': 2,
-                           'guard_false': 2, 'guard_value': 2})
-
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1, "float_neg": 1,
+                                "setinteriorfield_raw": 1, "int_add": 3,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def define_specialization():
         return """
@@ -249,10 +243,28 @@
     def test_slice(self):
         result = self.run("slice")
         assert result == 18
-        py.test.skip("Few remaining arraylen_gc left")
-        self.check_loops({'int_mul': 2, 'getarrayitem_raw': 2, 'float_add': 1,
-                          'setarrayitem_raw': 1, 'int_add': 3,
-                          'int_lt': 1, 'guard_true': 1, 'jump': 1})
+        self.check_simple_loop({'getinteriorfield_raw': 2,
+                                'float_add': 1,
+                                'setinteriorfield_raw': 1,
+                                'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1,
+                                'jump': 1})
+
+    def define_slice2():
+        return """
+        a = |30|
+        s1 = a -> :20:2
+        s2 = a -> :30:3
+        b = s1 + s2
+        b -> 3
+        """
+
+    def test_slice2(self):
+        result = self.run("slice2")
+        assert result == 15
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1, 'jump': 1})
 
     def define_multidim():
         return """
@@ -264,12 +276,11 @@
     def test_multidim(self):
         result = self.run('multidim')
         assert result == 8
-        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
-                           'int_add': 6, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
-                           'guard_value': 1})
         # int_add might be 1 here if we try slightly harder with
         # reusing indexes or some optimization
+        self.check_simple_loop({'float_add': 1, 'getinteriorfield_raw': 2,
+                                'guard_false': 1, 'int_add': 3, 'int_ge': 1,
+                                'jump': 1, 'setinteriorfield_raw': 1})
 
     def define_multidim_slice():
         return """
@@ -285,7 +296,7 @@
         py.test.skip("improve")
         # XXX the bridge here is scary. Hopefully jit-targets will fix that,
         #     otherwise it looks kind of good
-        self.check_loops({})
+        self.check_simple_loop({})
 
     def define_broadcast():
         return """
@@ -299,58 +310,34 @@
         result = self.run("broadcast")
         assert result == 10
         py.test.skip("improve")
-        self.check_loops({})
+        self.check_simple_loop({})
+
+    def define_setslice():
+        return """
+        a = |30|
+        b = |10|
+        b[1] = 5.5
+        c = b + b
+        a[0:30:3] = c
+        a -> 3
+        """
+
+    def test_setslice(self):
+        result = self.run("setslice")
+        assert result == 11.0
+        self.check_loop_count(1)
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_eq': 1, 'guard_false': 1, 'jump': 1})
 
 class TestNumpyOld(LLJitMixin):
     def setup_class(cls):
         py.test.skip("old")
         from pypy.module.micronumpy.compile import FakeSpace
-        from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+        from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 
         cls.space = FakeSpace()
-        cls.float64_dtype = cls.space.fromcache(W_Float64Dtype)
-
-    def test_slice2(self):
-        def f(i):
-            step1 = 2
-            step2 = 3
-            ar = NDimArray(step2*i, dtype=self.float64_dtype)
-            new_sig = signature.Signature.find_sig([
-                NDimSlice.signature, ar.signature
-            ])
-            s1 = NDimSlice(0, step1*i, step1, i, ar, new_sig)
-            new_sig = signature.Signature.find_sig([
-                NDimSlice.signature, s1.signature
-            ])
-            s2 = NDimSlice(0, step2*i, step2, i, ar, new_sig)
-            v = interp_ufuncs.get(self.space).add.call(self.space, [s1, s2])
-            return v.get_concrete().eval(3).val
-
-        result = self.meta_interp(f, [5], listops=True, backendopt=True)
-        self.check_loops({'int_mul': 2, 'getarrayitem_raw': 2, 'float_add': 1,
-                          'setarrayitem_raw': 1, 'int_add': 1,
-                          'int_lt': 1, 'guard_true': 1, 'jump': 1})
-        assert result == f(5)
-
-    def test_setslice(self):
-        space = self.space
-        float64_dtype = self.float64_dtype
-
-        def f(i):
-            step = NonConstant(3)
-            ar = NDimArray(step*i, dtype=float64_dtype)
-            ar2 = NDimArray(i, dtype=float64_dtype)
-            ar2.get_concrete().setitem(1, float64_dtype.box(5.5))
-            arg = ar2.descr_add(space, ar2)
-            ar.setslice(space, 0, step*i, step, i, arg)
-            return ar.get_concrete().eval(3).val
-
-        result = self.meta_interp(f, [5], listops=True, backendopt=True)
-        self.check_loops({'getarrayitem_raw': 2,
-                          'float_add' : 1,
-                          'setarrayitem_raw': 1, 'int_add': 2,
-                          'int_lt': 1, 'guard_true': 1, 'jump': 1})
-        assert result == 11.0
+        cls.float64_dtype = get_dtype_cache(cls.space).w_float64dtype
 
     def test_int32_sum(self):
         py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to "
@@ -365,7 +352,7 @@
                 dtype = float64_dtype
             else:
                 dtype = int32_dtype
-            ar = NDimArray(n, [n], dtype=dtype)
+            ar = W_NDimArray(n, [n], dtype=dtype)
             i = 0
             while i < n:
                 ar.get_concrete().setitem(i, int32_dtype.box(7))
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/types.py
@@ -0,0 +1,389 @@
+import functools
+import math
+
+from pypy.module.micronumpy import interp_boxes
+from pypy.objspace.std.floatobject import float2string
+from pypy.rlib import rfloat, libffi, clibffi
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT, widen
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def simple_unary_op(func):
+    specialize.argtype(1)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v):
+        return self.box(
+            func(
+                self,
+                self.for_computation(self.unbox(v))
+            )
+        )
+    return dispatcher
+
+def simple_binary_op(func):
+    specialize.argtype(1, 2)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v1, v2):
+        return self.box(
+            func(
+                self,
+                self.for_computation(self.unbox(v1)),
+                self.for_computation(self.unbox(v2)),
+            )
+        )
+    return dispatcher
+
+def raw_binary_op(func):
+    specialize.argtype(1, 2)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v1, v2):
+        return func(self,
+            self.for_computation(self.unbox(v1)),
+            self.for_computation(self.unbox(v2))
+        )
+    return dispatcher
+
+class BaseType(object):
+    def _unimplemented_ufunc(self, *args):
+        raise NotImplementedError
+    # add = sub = mul = div = mod = pow = eq = ne = lt = le = gt = ge = max = \
+    #     min = copysign = pos = neg = abs = sign = reciprocal = fabs = floor = \
+    #     exp = sin = cos = tan = arcsin = arccos = arctan = arcsinh = \
+    #     arctanh = _unimplemented_ufunc
+
+class Primitive(object):
+    _mixin_ = True
+    def get_element_size(self):
+        return rffi.sizeof(self.T)
+
+    @specialize.argtype(1)
+    def box(self, value):
+        return self.BoxType(rffi.cast(self.T, value))
+
+    def unbox(self, box):
+        assert isinstance(box, self.BoxType)
+        return box.value
+
+    def coerce(self, space, w_item):
+        if isinstance(w_item, self.BoxType):
+            return w_item
+        return self.coerce_subtype(space, space.gettypefor(self.BoxType), w_item)
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # XXX: ugly
+        w_obj = space.allocate_instance(self.BoxType, w_subtype)
+        assert isinstance(w_obj, self.BoxType)
+        w_obj.__init__(self._coerce(space, w_item).value)
+        return w_obj
+
+    def _coerce(self, space, w_item):
+        raise NotImplementedError
+
+    def read(self, storage, width, i, offset):
+        return self.box(libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+            width, storage, i, offset
+        ))
+
+    def store(self, storage, width, i, offset, box):
+        value = self.unbox(box)
+        libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+            width, storage, i, offset, value
+        )
+
+    def fill(self, storage, width, box, start, stop, offset):
+        value = self.unbox(box)
+        for i in xrange(start, stop):
+            libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+                width, storage, i, offset, value
+            )
+
+    @simple_binary_op
+    def add(self, v1, v2):
+        return v1 + v2
+
+    @simple_binary_op
+    def sub(self, v1, v2):
+        return v1 - v2
+
+    @simple_binary_op
+    def mul(self, v1, v2):
+        return v1 * v2
+
+    @simple_unary_op
+    def pos(self, v):
+        return +v
+
+    @simple_unary_op
+    def neg(self, v):
+        return -v
+
+    @simple_unary_op
+    def abs(self, v):
+        return abs(v)
+
+    @raw_binary_op
+    def eq(self, v1, v2):
+        return v1 == v2
+
+    @raw_binary_op
+    def ne(self, v1, v2):
+        return v1 != v2
+
+    @raw_binary_op
+    def lt(self, v1, v2):
+        return v1 < v2
+
+    @raw_binary_op
+    def le(self, v1, v2):
+        return v1 <= v2
+
+    @raw_binary_op
+    def gt(self, v1, v2):
+        return v1 > v2
+
+    @raw_binary_op
+    def ge(self, v1, v2):
+        return v1 >= v2
+
+    def bool(self, v):
+        return bool(self.for_computation(self.unbox(v)))
+
+    @simple_binary_op
+    def max(self, v1, v2):
+        return max(v1, v2)
+
+    @simple_binary_op
+    def min(self, v1, v2):
+        return min(v1, v2)
+
+class Bool(BaseType, Primitive):
+    T = lltype.Bool
+    BoxType = interp_boxes.W_BoolBox
+
+    True = BoxType(True)
+    False = BoxType(False)
+
+    @specialize.argtype(1)
+    def box(self, value):
+        box = Primitive.box(self, value)
+        if box.value:
+            return self.True
+        else:
+            return self.False
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # Doesn't return subclasses so it can return the constants.
+        return self._coerce(space, w_item)
+
+    def _coerce(self, space, w_item):
+        return self.box(space.is_true(w_item))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return "True" if value else "False"
+
+    def for_computation(self, v):
+        return int(v)
+
+class Integer(Primitive):
+    _mixin_ = True
+
+    def _coerce(self, space, w_item):
+        return self.box(space.int_w(space.int(w_item)))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return str(self.for_computation(value))
+
+    def for_computation(self, v):
+        return widen(v)
+
+    @simple_binary_op
+    def div(self, v1, v2):
+        if v2 == 0:
+            return 0
+        return v1 / v2
+
+    @simple_binary_op
+    def mod(self, v1, v2):
+        return v1 % v2
+
+    @simple_binary_op
+    def pow(self, v1, v2):
+        res = 1
+        while v2 > 0:
+            if v2 & 1:
+                res *= v1
+            v2 >>= 1
+            if v2 == 0:
+                break
+            v1 *= v1
+        return res
+
+    @simple_unary_op
+    def sign(self, v):
+        if v > 0:
+            return 1
+        elif v < 0:
+            return -1
+        else:
+            assert v == 0
+            return 0
+
+class Int8(BaseType, Integer):
+    T = rffi.SIGNEDCHAR
+    BoxType = interp_boxes.W_Int8Box
+
+class UInt8(BaseType, Integer):
+    T = rffi.UCHAR
+    BoxType = interp_boxes.W_UInt8Box
+
+class Int16(BaseType, Integer):
+    T = rffi.SHORT
+    BoxType = interp_boxes.W_Int16Box
+
+class UInt16(BaseType, Integer):
+    T = rffi.USHORT
+    BoxType = interp_boxes.W_UInt16Box
+
+class Int32(BaseType, Integer):
+    T = rffi.INT
+    BoxType = interp_boxes.W_Int32Box
+
+class UInt32(BaseType, Integer):
+    T = rffi.UINT
+    BoxType = interp_boxes.W_UInt32Box
+
+class Long(BaseType, Integer):
+    T = rffi.LONG
+    BoxType = interp_boxes.W_LongBox
+
+class ULong(BaseType, Integer):
+    T = rffi.ULONG
+    BoxType = interp_boxes.W_ULongBox
+
+class Int64(BaseType, Integer):
+    T = rffi.LONGLONG
+    BoxType = interp_boxes.W_Int64Box
+
+class UInt64(BaseType, Integer):
+    T = rffi.ULONGLONG
+    BoxType = interp_boxes.W_UInt64Box
+
+class Float(Primitive):
+    _mixin_ = True
+
+    def _coerce(self, space, w_item):
+        return self.box(space.float_w(space.float(w_item)))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return float2string(self.for_computation(value), "g", rfloat.DTSF_STR_PRECISION)
+
+    def for_computation(self, v):
+        return float(v)
+
+    @simple_binary_op
+    def div(self, v1, v2):
+        try:
+            return v1 / v2
+        except ZeroDivisionError:
+            if v1 == v2 == 0.0:
+                return rfloat.NAN
+            return rfloat.copysign(rfloat.INFINITY, v1 * v2)
+
+    @simple_binary_op
+    def mod(self, v1, v2):
+        return math.fmod(v1, v2)
+
+    @simple_binary_op
+    def pow(self, v1, v2):
+        return math.pow(v1, v2)
+
+    @simple_binary_op
+    def copysign(self, v1, v2):
+        return math.copysign(v1, v2)
+
+    @simple_unary_op
+    def sign(self, v):
+        if v == 0.0:
+            return 0.0
+        return rfloat.copysign(1.0, v)
+
+    @simple_unary_op
+    def fabs(self, v):
+        return math.fabs(v)
+
+    @simple_unary_op
+    def reciprocal(self, v):
+        if v == 0.0:
+            return rfloat.copysign(rfloat.INFINITY, v)
+        return 1.0 / v
+
+    @simple_unary_op
+    def floor(self, v):
+        return math.floor(v)
+
+    @simple_unary_op
+    def exp(self, v):
+        try:
+            return math.exp(v)
+        except OverflowError:
+            return rfloat.INFINITY
+
+    @simple_unary_op
+    def sin(self, v):
+        return math.sin(v)
+
+    @simple_unary_op
+    def cos(self, v):
+        return math.cos(v)
+
+    @simple_unary_op
+    def tan(self, v):
+        return math.tan(v)
+
+    @simple_unary_op
+    def arcsin(self, v):
+        if not -1.0 <= v <= 1.0:
+            return rfloat.NAN
+        return math.asin(v)
+
+    @simple_unary_op
+    def arccos(self, v):
+        if not -1.0 <= v <= 1.0:
+            return rfloat.NAN
+        return math.acos(v)
+
+    @simple_unary_op
+    def arctan(self, v):
+        return math.atan(v)
+
+    @simple_unary_op
+    def arcsinh(self, v):
+        return math.asinh(v)
+
+    @simple_unary_op
+    def arctanh(self, v):
+        if v == 1.0 or v == -1.0:
+            return math.copysign(rfloat.INFINITY, v)
+        if not -1.0 < v < 1.0:
+            return rfloat.NAN
+        return math.atanh(v)
+
+    @simple_unary_op
+    def sqrt(self, v):
+        try:
+            return math.sqrt(v)
+        except ValueError:
+            return rfloat.NAN
+
+
+class Float32(BaseType, Float):
+    T = rffi.FLOAT
+    BoxType = interp_boxes.W_Float32Box
+
+class Float64(BaseType, Float):
+    T = rffi.DOUBLE
+    BoxType = interp_boxes.W_Float64Box
\ No newline at end of file
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
 from pypy.rlib import rmmap
-from pypy.rlib.rmmap import RValueError, RTypeError, ROverflowError
+from pypy.rlib.rmmap import RValueError, RTypeError
 
 
 class W_MMap(Wrappable):
@@ -212,8 +212,6 @@
             raise OperationError(space.w_ValueError, space.wrap(e.message))
         except RTypeError, e:
             raise OperationError(space.w_TypeError, space.wrap(e.message))
-        except ROverflowError, e:
-            raise OperationError(space.w_OverflowError, space.wrap(e.message))
         return space.wrap(self)
 
 elif rmmap._MS_WINDOWS:
@@ -233,8 +231,6 @@
             raise OperationError(space.w_ValueError, space.wrap(e.message))
         except RTypeError, e:
             raise OperationError(space.w_TypeError, space.wrap(e.message))
-        except ROverflowError, e:
-            raise OperationError(space.w_OverflowError, space.wrap(e.message))
         return space.wrap(self)
 
 W_MMap.typedef = TypeDef("mmap",
diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.rpython.lltypesystem import lltype
-from pypy.rlib.rarithmetic import ovfcheck_float_to_int
+from pypy.rlib.rarithmetic import ovfcheck_float_to_int, intmask
 from pypy.rlib import rposix
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import os
@@ -585,7 +585,7 @@
                 # More likely, the format yields an empty result,
                 # e.g. an empty format, or %Z when the timezone
                 # is unknown.
-                result = rffi.charp2strn(outbuf, buflen)
+                result = rffi.charp2strn(outbuf, intmask(buflen))
                 return space.wrap(result)
         finally:
             lltype.free(outbuf, flavor='raw')
diff --git a/pypy/objspace/flow/model.py b/pypy/objspace/flow/model.py
--- a/pypy/objspace/flow/model.py
+++ b/pypy/objspace/flow/model.py
@@ -38,7 +38,6 @@
     def __init__(self, name, startblock, return_var=None):
         self.name        = name    # function name (possibly mangled already)
         self.startblock  = startblock
-        self.startblock.isstartblock = True
         # build default returnblock
         self.returnblock = Block([return_var or Variable()])
         self.returnblock.operations = ()
@@ -171,11 +170,10 @@
 
 
 class Block(object):
-    __slots__ = """isstartblock inputargs operations exitswitch
+    __slots__ = """inputargs operations exitswitch
                 exits blockcolor""".split()
     
     def __init__(self, inputargs):
-        self.isstartblock = False
         self.inputargs = list(inputargs)  # mixed list of variable/const XXX 
         self.operations = []              # list of SpaceOperation(s)
         self.exitswitch = None            # a variable or
@@ -452,7 +450,6 @@
         newblock.closeblock(*newlinks)
 
     newstartblock = blockmap[graph.startblock]
-    newstartblock.isstartblock = True
     newgraph = FunctionGraph(graph.name, newstartblock)
     newgraph.returnblock = blockmap[graph.returnblock]
     newgraph.exceptblock = blockmap[graph.exceptblock]
@@ -490,7 +487,6 @@
 
 
         for block in graph.iterblocks():
-            assert bool(block.isstartblock) == (block is graph.startblock)
             assert type(block.exits) is tuple, (
                 "block.exits is a %s (closeblock() or recloseblock() missing?)"
                 % (type(block.exits).__name__,))
diff --git a/pypy/objspace/flow/test/test_checkgraph.py b/pypy/objspace/flow/test/test_checkgraph.py
--- a/pypy/objspace/flow/test/test_checkgraph.py
+++ b/pypy/objspace/flow/test/test_checkgraph.py
@@ -13,20 +13,6 @@
     py.test.raises(AssertionError, checkgraph, g)
 
 
-def test_nostartblock():
-    g = FunctionGraph("g", Block([]))
-    g.startblock.closeblock(Link([Constant(1)], g.returnblock))
-    g.startblock.isstartblock = False
-    py.test.raises(AssertionError, checkgraph, g)
-
-def test_twostartblocks():
-    g = FunctionGraph("g", Block([]))
-    b = Block([])
-    b.isstartblock = True
-    g.startblock.closeblock(Link([], b))
-    b.closeblock(Link([Constant(1)], g.returnblock))
-    py.test.raises(AssertionError, checkgraph, g)
-
 def test_exitlessblocknotexitblock():
     g = FunctionGraph("g", Block([]))
     py.test.raises(AssertionError, checkgraph, g)
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
@@ -50,6 +50,13 @@
     else:
         return space.fromcache(StringListStrategy)
 
+    # check for floats
+    for w_obj in list_w:
+        if not is_W_FloatObject(w_obj):
+            break
+    else:
+        return space.fromcache(FloatListStrategy)
+
     return space.fromcache(ObjectListStrategy)
 
 def is_W_IntObject(w_object):
@@ -60,7 +67,9 @@
     from pypy.objspace.std.stringobject import W_StringObject
     return type(w_object) is W_StringObject
 
-
+def is_W_FloatObject(w_object):
+    from pypy.objspace.std.floatobject import W_FloatObject
+    return type(w_object) is W_FloatObject
 
 class W_ListObject(W_AbstractListObject):
     from pypy.objspace.std.listtype import list_typedef as typedef
@@ -317,6 +326,8 @@
     to the added item.
     W_Lists do not switch back to EmptyListStrategy when becoming empty again."""
 
+    _applevel_repr = "empty"
+
     def __init__(self, space):
         ListStrategy.__init__(self, space)
         # cache an empty list that is used whenever getitems is called (i.e. sorting)
@@ -364,6 +375,8 @@
             strategy = self.space.fromcache(IntegerListStrategy)
         elif is_W_StringObject(w_item):
             strategy = self.space.fromcache(StringListStrategy)
+        elif is_W_FloatObject(w_item):
+            strategy = self.space.fromcache(FloatListStrategy)
         else:
             strategy = self.space.fromcache(ObjectListStrategy)
 
@@ -415,6 +428,8 @@
     On any operation destroying the range (inserting, appending non-ints)
     the strategy is switched to IntegerListStrategy."""
 
+    _applevel_repr = "range"
+
     def switch_to_integer_strategy(self, w_list):
         items = self._getitems_range(w_list, False)
         strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
@@ -853,6 +868,7 @@
 
 class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = None
+    _applevel_repr = "object"
 
     def unwrap(self, w_obj):
         return w_obj
@@ -881,6 +897,7 @@
 
 class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = 0
+    _applevel_repr = "int"
 
     def wrap(self, intval):
         return self.space.wrap(intval)
@@ -905,8 +922,36 @@
         if reverse:
             l.reverse()
 
+class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+    _none_value = 0.0
+    _applevel_repr = "float"
+
+    def wrap(self, floatval):
+        return self.space.wrap(floatval)
+
+    def unwrap(self, w_float):
+        return self.space.float_w(w_float)
+
+    erase, unerase = rerased.new_erasing_pair("float")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def is_correct_type(self, w_obj):
+        return is_W_FloatObject(w_obj)
+
+    def list_is_correct_type(self, w_list):
+        return w_list.strategy is self.space.fromcache(FloatListStrategy)
+
+    def sort(self, w_list, reverse):
+        l = self.unerase(w_list.lstorage)
+        sorter = FloatSort(l, len(l))
+        sorter.sort()
+        if reverse:
+            l.reverse()
+
 class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = None
+    _applevel_repr = "str"
 
     def wrap(self, stringval):
         return self.space.wrap(stringval)
@@ -934,6 +979,7 @@
     def getitems_str(self, w_list):
         return self.unerase(w_list.lstorage)
 
+
 # _______________________________________________________
 
 init_signature = Signature(['sequence'], None, None)
@@ -1282,6 +1328,7 @@
 
 TimSort = make_timsort_class()
 IntBaseTimSort = make_timsort_class()
+FloatBaseTimSort = make_timsort_class()
 StringBaseTimSort = make_timsort_class()
 
 class KeyContainer(baseobjspace.W_Root):
@@ -1302,6 +1349,10 @@
     def lt(self, a, b):
         return a < b
 
+class FloatSort(FloatBaseTimSort):
+    def lt(self, a, b):
+        return a < b
+
 class StringSort(StringBaseTimSort):
     def lt(self, a, b):
         return a < b
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
@@ -453,12 +453,12 @@
     multi = r_uint(1822399083) + r_uint(1822399083) + 1
     if w_set.hash != 0:
         return space.wrap(w_set.hash)
-    hash = 1927868237
-    hash *= (len(w_set.setdata) + 1)
+    hash = r_uint(1927868237)
+    hash *= r_uint(len(w_set.setdata) + 1)
     for w_item in w_set.setdata:
         h = space.hash_w(w_item)
-        value = ((h ^ (h << 16) ^ 89869747)  * multi)
-        hash = intmask(hash ^ value)
+        value = (r_uint(h ^ (h << 16) ^ 89869747)  * multi)
+        hash = hash ^ value
     hash = hash * 69069 + 907133923
     if hash == 0:
         hash = 590923713
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
@@ -470,11 +470,17 @@
         l.extend(iter([1, 2, 3, 4]))
         assert l is l0
         assert l == [1, 1, 2, 3, 4]
+
         l = l0 = ['a']
         l.extend(iter(['b', 'c', 'd']))
         assert l == ['a', 'b', 'c', 'd']
         assert l is l0
 
+        l = l0 = [1.2]
+        l.extend(iter([2.3, 3.4, 4.5]))
+        assert l == [1.2, 2.3, 3.4, 4.5]
+        assert l is l0
+
     def test_sort(self):
         l = l0 = [1, 5, 3, 0]
         l.sort()
@@ -493,6 +499,10 @@
         l.sort(reverse=True)
         assert l == ["d", "c", "b", "a"]
 
+        l = [3.3, 2.2, 4.4, 1.1, 3.1, 5.5]
+        l.sort()
+        assert l == [1.1, 2.2, 3.1, 3.3, 4.4, 5.5]
+
     def test_sort_cmp(self):
         def lencmp(a,b): return cmp(len(a), len(b))
         l = [ 'a', 'fiver', 'tre', '' ]
@@ -546,11 +556,19 @@
         assert l[-2] == 6
         raises(IndexError, "l[len(l)]")
         raises(IndexError, "l[-len(l)-1]")
+
         l = ['a', 'b', 'c']
         assert l[0] == 'a'
         assert l[-1] == 'c'
         assert l[-2] == 'b'
         raises(IndexError, "l[len(l)]")
+
+        l = [1.1, 2.2, 3.3]
+        assert l[0] == 1.1
+        assert l[-1] == 3.3
+        assert l[-2] == 2.2
+        raises(IndexError, "l[len(l)]")
+
         l = []
         raises(IndexError, "l[1]")
 
@@ -588,6 +606,16 @@
         assert l is l0
         raises(IndexError, "del l[0]")
 
+        l = l0 = [1.1, 2.2, 3.3]
+        del l[0]
+        assert l == [2.2, 3.3]
+        del l[-1]
+        assert l == [2.2]
+        del l[-1]
+        assert l == []
+        assert l is l0
+        raises(IndexError, "del l[0]")
+
         l = range(10)
         del l[5]
         assert l == [0, 1, 2, 3, 4, 6, 7, 8, 9]
@@ -627,9 +655,15 @@
         del l[:]
         assert l is l0
         assert l == []
+
         l = ['a', 'b']
         del l[:]
         assert l == []
+
+        l = [1.1, 2.2]
+        del l[:]
+        assert l == []
+
         l = range(5)
         del l[:]
         assert l == []
@@ -640,6 +674,11 @@
         assert l is l0
         assert l == [1,2,3,4,5]
 
+        l = l0 = [1.1,2.2,3.3]
+        l += [4.4,5.5]
+        assert l is l0
+        assert l == [1.1,2.2,3.3,4.4,5.5]
+
         l = l0 = ['a', 'b', 'c']
         l1 = l[:]
         l += ['d']
@@ -697,6 +736,11 @@
         l *= -5
         assert l == []
 
+        l = l0 = [1.1, 2.2]
+        l *= 2
+        assert l is l0
+        assert l == [1.1, 2.2, 1.1, 2.2]
+
         l = range(2)
         l *= 2
         assert l == [0, 1, 0, 1]
@@ -731,6 +775,10 @@
         assert c.index(0) == 0
         raises(ValueError, c.index, 3)
 
+        c = [0.0, 2.2, 4.4]
+        assert c.index(0) == 0.0
+        raises(ValueError, c.index, 3)
+
     def test_index_cpython_bug(self):
         if self.on_cpython:
             skip("cpython has a bug here")
@@ -779,6 +827,10 @@
         l[::3] = ('a', 'b')
         assert l == ['a', 1, 2, 'b', 4, 5]
 
+        l = [0.0, 1.1, 2.2, 3.3, 4.4, 5.5]
+        l[::3] = ('a', 'b')
+        assert l == ['a', 1.1, 2.2, 'b', 4.4, 5.5]
+
     def test_setslice_with_self(self):
         l = [1,2,3,4]
         l[:] = l
@@ -835,6 +887,10 @@
         l.append("a")
         assert l == [1,2,3,"a"]
 
+        l = [1.1, 2.2, 3.3]
+        l.append(4.4)
+        assert l == [1.1, 2.2, 3.3, 4.4]
+
     def test_count(self):
         c = list('hello')
         assert c.count('l') == 2
@@ -875,6 +931,10 @@
         l.pop()
         assert l == range(9)
 
+        l = [1.1, 2.2, 3.3]
+        l.pop()
+        assert l == [1.1, 2.2]
+
         l = []
         raises(IndexError, l.pop, 0)
 
@@ -897,16 +957,19 @@
         l2 = ["1", "2", "3", "4"]
         l3 = range(5)
         l4 = [1, 2, 3, "4"]
+        l5 = [1.1, 2.2, 3.3, 4.4]
 
         raises(IndexError, l1.pop, -5)
         raises(IndexError, l2.pop, -5)
         raises(IndexError, l3.pop, -6)
         raises(IndexError, l4.pop, -5)
+        raises(IndexError, l5.pop, -5)
 
         assert l1.pop(-2) == 3
         assert l2.pop(-2) == "3"
         assert l3.pop(-2) == 3
         assert l4.pop(-2) == 3
+        assert l5.pop(-2) == 3.3
 
     def test_remove(self):
         c = list('hello world')
@@ -925,6 +988,13 @@
         l = [0, 3, 5]
         raises(ValueError, c.remove, 2)
 
+        l = [0.0, 1.1, 2.2, 3.3, 4.4]
+        l.remove(2.2)
+        assert l == [0.0, 1.1, 3.3, 4.4]
+        l = [0.0, 3.3, 5.5]
+        raises(ValueError, c.remove, 2)
+        raises(ValueError, c.remove, 2.2)
+
     def test_reverse(self):
         c = list('hello world')
         c.reverse()
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
@@ -1,4 +1,4 @@
-from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, StringListStrategy, RangeListStrategy, make_range_list
+from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, FloatListStrategy, StringListStrategy, RangeListStrategy, make_range_list
 from pypy.objspace.std import listobject
 from pypy.objspace.std.test.test_listobject import TestW_ListObject
 
@@ -15,7 +15,7 @@
     def test_empty_to_any(self):
         l = W_ListObject(self.space, [])
         assert isinstance(l.strategy, EmptyListStrategy)
-        l.append(self.space.wrap(1.))
+        l.append(self.space.wrap((1,3)))
         assert isinstance(l.strategy, ObjectListStrategy)
 
         l = W_ListObject(self.space, [])
@@ -28,6 +28,11 @@
         l.append(self.space.wrap('a'))
         assert isinstance(l.strategy, StringListStrategy)
 
+        l = W_ListObject(self.space, [])
+        assert isinstance(l.strategy, EmptyListStrategy)
+        l.append(self.space.wrap(1.2))
+        assert isinstance(l.strategy, FloatListStrategy)
+
     def test_int_to_any(self):
         l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
@@ -44,6 +49,14 @@
         l.append(self.space.wrap(3))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+    def test_float_to_any(self):
+        l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.append(self.space.wrap(4.4))
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.append(self.space.wrap("a"))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_setitem(self):
         # This should work if test_listobject.py passes
         l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
@@ -65,6 +78,12 @@
         l.setitem(0, self.space.wrap(2))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # FloatStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.2),self.space.wrap(2.3),self.space.wrap(3.4)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.setitem(0, self.space.wrap("a"))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_insert(self):
         # no change
         l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
@@ -84,6 +103,12 @@
         l.insert(3, self.space.wrap('d'))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # FloatStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.insert(3, self.space.wrap('d'))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
         # EmptyStrategy
         l = W_ListObject(self.space, [])
         assert isinstance(l.strategy, EmptyListStrategy)
@@ -95,7 +120,9 @@
         l.insert(0, self.space.wrap(2))
         assert isinstance(l.strategy, IntegerListStrategy)
 
-    def notest_list_empty_after_delete(self):
+    def test_list_empty_after_delete(self):
+        import py
+        py.test.skip("return to emptyliststrategy is not supported anymore")
         l = W_ListObject(self.space, [self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.deleteitem(0)
@@ -117,21 +144,36 @@
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        # IntegerStrategy to IntegerStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        # ObjectStrategy to ObjectStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap('b'), self.space.wrap(3)])
         assert isinstance(l.strategy, ObjectListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # IntegerStrategy to ObjectStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')]))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # StringStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')])
+        assert isinstance(l.strategy, StringListStrategy)
+        l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
+        # FloatStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap(2), self.space.wrap(3)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_setslice_List(self):
 
         def wrapitems(items):
@@ -160,6 +202,11 @@
         keep_other_strategy(l, 0, 2, other.length(), other)
         assert l.strategy is self.space.fromcache(StringListStrategy)
 
+        l = W_ListObject(self.space, wrapitems([1.1, 2.2, 3.3, 4.4, 5.5]))
+        other = W_ListObject(self.space, [])
+        keep_other_strategy(l, 0, 1, l.length(), other)
+        assert l.strategy is self.space.fromcache(FloatListStrategy)
+
         l = W_ListObject(self.space, wrapitems(["a",3,"c",4,"e"]))
         other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
         keep_other_strategy(l, 0, 2, other.length(), other)
@@ -194,6 +241,11 @@
         l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_empty_extend_with_any(self):
         empty = W_ListObject(self.space, [])
         assert isinstance(empty.strategy, EmptyListStrategy)
@@ -220,6 +272,11 @@
 
         empty = W_ListObject(self.space, [])
         assert isinstance(empty.strategy, EmptyListStrategy)
+        empty.extend(W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)]))
+        assert isinstance(empty.strategy, FloatListStrategy)
+
+        empty = W_ListObject(self.space, [])
+        assert isinstance(empty.strategy, EmptyListStrategy)
         empty.extend(W_ListObject(self.space, []))
         assert isinstance(empty.strategy, EmptyListStrategy)
 
@@ -293,12 +350,13 @@
         l.setslice(0, 1, 3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
-    def test_get_items_copy(self):
+    def test_copy_list(self):
         l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
-        l2 = l1.getitems()
+        l2 = l1.clone()
         l2.append(self.space.wrap(4))
         assert not l2 == l1.getitems()
 
+    def test_getitems_does_not_copy_object_list(self):
         l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap("two"), self.space.wrap(3)])
         l2 = l1.getitems()
         l2.append(self.space.wrap("four"))
@@ -345,7 +403,6 @@
         # should not raise
         assert getslice__List_ANY_ANY(self.space, l, self.space.wrap(15), self.space.wrap(2222)).strategy == self.space.fromcache(EmptyListStrategy)
 
-
     def test_add_to_rangelist(self):
         l1 = make_range_list(self.space, 1, 1, 3)
         l2 = W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5)])
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -102,6 +102,7 @@
                           'instancetypedef',
                           'terminator',
                           '_version_tag?',
+                          'name?',
                           ]
 
     # for config.objspace.std.getattributeshortcut
diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py
--- a/pypy/rlib/_rsocket_rffi.py
+++ b/pypy/rlib/_rsocket_rffi.py
@@ -418,7 +418,7 @@
 if _MSVC:
     def invalid_socket(fd):
         return fd == INVALID_SOCKET
-    INVALID_SOCKET = cConfig.INVALID_SOCKET
+    INVALID_SOCKET = intmask(cConfig.INVALID_SOCKET)
 else:
     def invalid_socket(fd):
         return fd < 0
diff --git a/pypy/rlib/_stacklet_n_a.py b/pypy/rlib/_stacklet_n_a.py
--- a/pypy/rlib/_stacklet_n_a.py
+++ b/pypy/rlib/_stacklet_n_a.py
@@ -1,4 +1,5 @@
 from pypy.rlib import _rffi_stacklet as _c
+from pypy.rlib import objectmodel, debug
 from pypy.rpython.annlowlevel import llhelper
 from pypy.tool.staticmethods import StaticMethods
 
@@ -21,6 +22,9 @@
 
     def destroy(thrd, h):
         _c.destroy(thrd._thrd, h)
+        if objectmodel.we_are_translated():
+            debug.debug_print("not using a framework GC: "
+                              "stacklet_destroy() may leak")
 
     is_empty_handle = _c.is_empty_handle
 
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -176,7 +176,6 @@
     return decorator
 
 @oopspec("jit.isconstant(value)")
- at specialize.ll()
 def isconstant(value):
     """
     While tracing, returns whether or not the value is currently known to be
@@ -186,9 +185,9 @@
     This is for advanced usage only.
     """
     return NonConstant(False)
+isconstant._annspecialcase_ = "specialize:call_location"
 
 @oopspec("jit.isvirtual(value)")
- at specialize.ll()
 def isvirtual(value):
     """
     Returns if this value is virtual, while tracing, it's relatively
@@ -197,6 +196,7 @@
     This is for advanced usage only.
     """
     return NonConstant(False)
+isvirtual._annspecialcase_ = "specialize:call_location"
 
 class Entry(ExtRegistryEntry):
     _about_ = hint
@@ -738,3 +738,29 @@
         return hop.genop('jit_marker', vlist,
                          resulttype=lltype.Void)
 
+def record_known_class(value, cls):
+    """
+    Assure the JIT that value is an instance of cls. This is not a precise
+    class check, unlike a guard_class.
+    """
+    assert isinstance(value, cls)
+
+
+class Entry(ExtRegistryEntry):
+    _about_ = record_known_class
+
+    def compute_result_annotation(self, s_inst, s_cls):
+        from pypy.annotation import model as annmodel
+        assert s_cls.is_constant()
+        assert not s_inst.can_be_none()
+        assert isinstance(s_inst, annmodel.SomeInstance)
+
+    def specialize_call(self, hop):
+        from pypy.rpython.lltypesystem import lltype, rclass
+        classrepr = rclass.get_type_repr(hop.rtyper)
+
+        hop.exception_cannot_occur()
+        v_inst = hop.inputarg(hop.args_r[0], arg=0)
+        v_cls = hop.inputarg(classrepr, arg=1)
+        return hop.genop('jit_record_known_class', [v_inst, v_cls],
+                         resulttype=lltype.Void)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -411,6 +411,10 @@
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
 
+# These specialize.call_location's should really be specialize.arg(0), however
+# you can't hash a pointer obj, which the specialize machinery wants to do.
+# Given the present usage of these functions, it's good enough.
+ at specialize.call_location()
 @jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
 def array_getitem(ffitype, width, addr, index, offset):
     for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -420,6 +424,7 @@
             return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
     assert False
 
+ at specialize.call_location()
 @jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
 def array_setitem(ffitype, width, addr, index, offset, value):
     for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -428,4 +433,4 @@
             addr = rffi.ptradd(addr, offset)
             rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
             return
-    assert False
\ No newline at end of file
+    assert False
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -91,9 +91,18 @@
 
         return decorated_func
 
+    def call_location(self):
+        """ Specializes the function for each call site.
+        """
+        def decorated_func(func):
+            func._annspecialcase_ = "specialize:call_location"
+            return func
+
+        return decorated_func
+
     def _wrap(self, args):
         return "("+','.join([repr(arg) for arg in args]) +")"
-        
+
 specialize = _Specialize()
 
 def enforceargs(*args):
@@ -125,7 +134,7 @@
 
     def __hash__(self):
         raise TypeError("Symbolics are not hashable!")
-    
+
     def __nonzero__(self):
         raise TypeError("Symbolics are not comparable")
 
@@ -155,7 +164,7 @@
     def lltype(self):
         from pypy.rpython.lltypesystem import lltype
         return lltype.Signed
-    
+
 malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
 running_on_llinterp = CDefinedIntSymbolic('RUNNING_ON_LLINTERP', default=1)
 # running_on_llinterp is meant to have the value 0 in all backends
@@ -221,7 +230,7 @@
 
     def compute_result_annotation(self, s_sizehint):
         from pypy.annotation.model import SomeInteger
-        
+
         assert isinstance(s_sizehint, SomeInteger)
         return self.bookkeeper.newlist()
 
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -143,7 +143,9 @@
         return self_type
     if self_type in (bool, int, long):
         return other_type
-    return build_int(None, self_type.SIGNED and other_type.SIGNED, max(self_type.BITS, other_type.BITS))
+    if self_type.SIGNED == other_type.SIGNED:
+        return build_int(None, self_type.SIGNED, max(self_type.BITS, other_type.BITS))
+    raise AssertionError, "Merging these types (%s, %s) is not supported" % (self_type, other_type)
 
 def signedtype(t):
     if t in (bool, int, long):
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -229,7 +229,7 @@
         sign = self.sign
         if intmask(x) < 0 and (sign > 0 or (x << 1) != 0):
             raise OverflowError
-        return intmask(x * sign)
+        return intmask(intmask(x) * sign)
 
     def tolonglong(self):
         return _AsLongLong(self)
@@ -1384,7 +1384,7 @@
 
     # Now remove the excess 2 bits, rounding to nearest integer (with
     # ties rounded to even).
-    q = (q >> 2) + (bool(q & 2) and bool(q & 5))
+    q = (q >> 2) + r_uint((bool(q & 2) and bool(q & 5)))
 
     if exp > DBL_MAX_EXP or (exp == DBL_MAX_EXP and
                              q == r_ulonglong(1) << DBL_MANT_DIG):
@@ -1540,8 +1540,8 @@
     assert extra_bits == 2 or extra_bits == 3
 
     # Round by remembering a modified copy of the low digit of x
-    mask = 1 << (extra_bits - 1)
-    low = x.udigit(0) | inexact
+    mask = r_uint(1 << (extra_bits - 1))
+    low = x.udigit(0) | r_uint(inexact)
     if (low & mask) != 0 and (low & (3*mask-1)) != 0:
         low += mask
     x_digit_0 = low & ~(mask-1)
@@ -1790,7 +1790,7 @@
     i = v.numdigits() - 1
     while i >= 0:
         prev = x
-        x = (x << SHIFT) + v.widedigit(i)
+        x = (x << SHIFT) + r_ulonglong(v.widedigit(i))
         if (x >> SHIFT) != prev:
                 raise OverflowError(
                     "long int too large to convert to unsigned long long int")
@@ -1833,8 +1833,8 @@
         if x < v.udigit(i):
             x += 1
         i -= 1
-    x = intmask(x * sign)
-    return x
+    res = intmask(intmask(x) * sign)
+    return res
 
 #_________________________________________________________________
 
diff --git a/pypy/rlib/rmmap.py b/pypy/rlib/rmmap.py
--- a/pypy/rlib/rmmap.py
+++ b/pypy/rlib/rmmap.py
@@ -23,10 +23,6 @@
     def __init__(self, message):
         self.message = message
 
-class ROverflowError(Exception):
-    def __init__(self, message):
-        self.message = message
-
 includes = ["sys/types.h"]
 if _POSIX:
     includes += ['unistd.h', 'sys/mman.h']
@@ -597,8 +593,6 @@
 def _check_map_size(size):
     if size < 0:
         raise RTypeError("memory mapped size must be positive")
-    if rffi.cast(size_t, size) != size:
-        raise ROverflowError("memory mapped size is too large (limited by C int)")
 
 if _POSIX:
     def mmap(fileno, length, flags=MAP_SHARED,
diff --git a/pypy/rlib/rrandom.py b/pypy/rlib/rrandom.py
--- a/pypy/rlib/rrandom.py
+++ b/pypy/rlib/rrandom.py
@@ -31,7 +31,7 @@
         mt[0]= s & MASK_32
         for mti in range(1, N):
             mt[mti] = (MAGIC_CONSTANT_A *
-                           (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti)
+                           (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + r_uint(mti))
             # See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
             # In the previous versions, MSBs of the seed affect
             # only MSBs of the array mt[].
@@ -52,7 +52,7 @@
         for k in range(max_k, 0, -1):
             mt[i] = ((mt[i] ^
                          ((mt[i - 1] ^ (mt[i - 1] >> 30)) * MAGIC_CONSTANT_C))
-                     + init_key[j] + j) # non linear
+                     + init_key[j] + r_uint(j)) # non linear
             mt[i] &= MASK_32 # for WORDSIZE > 32 machines
             i += 1
             j += 1
@@ -104,5 +104,5 @@
             j = n % i
             mt[i], mt[j] = mt[j], mt[i]
         for i in range(N):
-            mt[i] += i + 1
+            mt[i] += r_uint(i + 1)
         self.index = N
diff --git a/pypy/rlib/rsocket.py b/pypy/rlib/rsocket.py
--- a/pypy/rlib/rsocket.py
+++ b/pypy/rlib/rsocket.py
@@ -17,7 +17,7 @@
 
 from pypy.rlib.objectmodel import instantiate, keepalive_until_here
 from pypy.rlib import _rsocket_rffi as _c
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.lltypesystem.rffi import sizeof, offsetof
 
@@ -131,11 +131,12 @@
     from_object = staticmethod(from_object)
 
     @staticmethod
-    def _check_port(space, port):
+    def make_ushort_port(space, port):
         from pypy.interpreter.error import OperationError
         if port < 0 or port > 0xffff:
             raise OperationError(space.w_ValueError, space.wrap(
                 "port must be 0-65535."))
+        return rffi.cast(rffi.USHORT, port)
 
     def fill_from_object(self, space, w_address):
         """ Purely abstract
@@ -167,7 +168,7 @@
 
     # IPv4 also supports the special name "<broadcast>".
     if name == '<broadcast>':
-        return makeipv4addr(intmask(INADDR_BROADCAST), result)
+        return makeipv4addr(r_uint(INADDR_BROADCAST), result)
 
     # "dd.dd.dd.dd" format.
     digits = name.split('.')
@@ -184,9 +185,11 @@
                 0 <= d1 <= 255 and
                 0 <= d2 <= 255 and
                 0 <= d3 <= 255):
-                return makeipv4addr(intmask(htonl(
-                    (intmask(d0 << 24)) | (d1 << 16) | (d2 << 8) | (d3 << 0))),
-                                    result)
+
+                addr = intmask(d0 << 24) | (d1 << 16) | (d2 << 8) | (d3 << 0)
+                addr = rffi.cast(rffi.UINT, addr)
+                addr = htonl(addr)
+                return makeipv4addr(addr, result)
 
     # generic host name to IP conversion
     info = getaddrinfo(name, None, family=family, address_to_fill=result)
@@ -236,7 +239,9 @@
 
         def get_protocol(self):
             a = self.lock(_c.sockaddr_ll)
-            res = ntohs(rffi.getintfield(a, 'c_sll_protocol'))
+            proto = rffi.getintfield(a, 'c_sll_protocol')
+            proto = rffi.cast(rffi.USHORT, proto)
+            res = ntohs(proto)
             self.unlock()
             return res
 
@@ -277,6 +282,7 @@
     def __init__(self, host, port):
         makeipaddr(host, self)
         a = self.lock(_c.sockaddr_in)
+        port = rffi.cast(rffi.USHORT, port)
         rffi.setintfield(a, 'c_sin_port', htons(port))
         self.unlock()
 
@@ -309,7 +315,7 @@
             raise TypeError("AF_INET address must be a tuple of length 2")
         host = space.str_w(w_host)
         port = space.int_w(w_port)
-        Address._check_port(space, port)
+        port = Address.make_ushort_port(space, port)
         return INETAddress(host, port)
     from_object = staticmethod(from_object)
 
@@ -318,7 +324,7 @@
         from pypy.interpreter.error import OperationError
         _, w_port = space.unpackiterable(w_address, 2)
         port = space.int_w(w_port)
-        self._check_port(space, port)
+        port = self.make_ushort_port(space, port)
         a = self.lock(_c.sockaddr_in)
         rffi.setintfield(a, 'c_sin_port', htons(port))
         self.unlock()
@@ -403,7 +409,7 @@
                                "to 4, not %d" % len(pieces_w))
         host = space.str_w(pieces_w[0])
         port = space.int_w(pieces_w[1])
-        Address._check_port(space, port)
+        port = Address.make_ushort_port(space, port)
         if len(pieces_w) > 2: flowinfo = space.uint_w(pieces_w[2])
         else:                 flowinfo = 0
         if len(pieces_w) > 3: scope_id = space.uint_w(pieces_w[3])
@@ -419,7 +425,7 @@
             raise RSocketError("AF_INET6 address must be a tuple of length 2 "
                                "to 4, not %d" % len(pieces_w))
         port = space.int_w(pieces_w[1])
-        self._check_port(space, port)
+        port = self.make_ushort_port(space, port)
         if len(pieces_w) > 2: flowinfo = space.uint_w(pieces_w[2])
         else:                 flowinfo = 0
         if len(pieces_w) > 3: scope_id = space.uint_w(pieces_w[3])
@@ -1295,9 +1301,13 @@
     servent = _c.getservbyname(name, proto)
     if not servent:
         raise RSocketError("service/proto not found")
-    return ntohs(servent.c_s_port)
+    port = rffi.cast(rffi.UINT, servent.c_s_port)
+    return ntohs(port)
 
 def getservbyport(port, proto=None):
+    # This function is only called from pypy/module/_socket and the range of
+    # port is checked there
+    port = rffi.cast(rffi.USHORT, port)
     servent = _c.getservbyport(htons(port), proto)
     if not servent:
         raise RSocketError("port/proto not found")
diff --git a/pypy/rlib/rstruct/standardfmttable.py b/pypy/rlib/rstruct/standardfmttable.py
--- a/pypy/rlib/rstruct/standardfmttable.py
+++ b/pypy/rlib/rstruct/standardfmttable.py
@@ -206,7 +206,7 @@
                 if signed and i == 0 and x >= 128:
                     x -= 256
                 intvalue <<= 8
-                intvalue |= x
+                intvalue |= inttype(x)
                 idx += 1
         else:
             for i in unroll_range_size:
diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py
--- a/pypy/rlib/rwin32.py
+++ b/pypy/rlib/rwin32.py
@@ -98,8 +98,13 @@
     INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1)
     PFILETIME = rffi.CArrayPtr(FILETIME)
 
-    GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False)
-    SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
+    _GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False)
+    _SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
+
+    def GetLastError():
+        return rffi.cast(lltype.Signed, _GetLastError())
+    def SetLastError(err):
+        _SetLastError(rffi.cast(DWORD, err))
 
     # In tests, the first call to GetLastError is always wrong, because error
     # is hidden by operations in ll2ctypes.  Call it now.
@@ -184,12 +189,12 @@
             msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                    FORMAT_MESSAGE_FROM_SYSTEM,
                                    None,
-                                   code,
+                                   rffi.cast(DWORD, code),
                                    DEFAULT_LANGUAGE,
                                    rffi.cast(rffi.CCHARP, buf),
                                    0, None)
 
-            if msglen <= 2 or msglen > sys.maxint:
+            if msglen <= 2:   # includes the case msglen < 0
                 return fake_FormatError(code)
 
             # FormatMessage always appends \r\n.
diff --git a/pypy/rlib/test/test_rarithmetic.py b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -126,13 +126,18 @@
             cmp = f(r_uint(arg))
             assert res == cmp
         
-    def binary_test(self, f, rargs = None):
+    def binary_test(self, f, rargs = None, translated=False):
         mask = maxint_mask 
         if not rargs:
             rargs = (1, 3, 55)
+        # when translated merging different int types is not allowed
+        if translated:
+            alltypes = [(r_uint, r_uint)]
+        else:
+            alltypes = [(int, r_uint), (r_uint, int), (r_uint, r_uint)]
         for larg in (0, 1, 2, 3, 1234):
             for rarg in rargs:
-                for types in ((int, r_uint), (r_uint, int), (r_uint, r_uint)):
+                for types in alltypes:
                     res = f(larg, rarg)
                     left, right = types
                     cmp = f(left(larg), right(rarg))
@@ -335,6 +340,14 @@
     from pypy.rpython.lltypesystem.rffi import r_int_real
     assert compute_restype(r_int_real, r_int_real) is r_int_real
 
+def test_compute_restype_incompatible():
+    from pypy.rpython.lltypesystem.rffi import r_int_real, r_short, r_ushort
+    testcases = [(r_uint, r_longlong), (r_int_real, r_uint),
+                (r_short, r_ushort)]
+    for t1, t2 in testcases:
+        py.test.raises(AssertionError, compute_restype, t1, t2)
+        py.test.raises(AssertionError, compute_restype, t2, t1)
+
 def test_most_neg_value_of():
     assert most_neg_value_of_same_type(123) == -sys.maxint-1
     assert most_neg_value_of_same_type(r_uint(123)) == 0
diff --git a/pypy/rlib/test/test_rrandom.py b/pypy/rlib/test/test_rrandom.py
--- a/pypy/rlib/test/test_rrandom.py
+++ b/pypy/rlib/test/test_rrandom.py
@@ -1,4 +1,5 @@
 from pypy.rlib.rrandom import Random, N, r_uint
+from pypy.rlib.rarithmetic import intmask
 import _random
 
 # the numbers were created by using CPython's _randommodule.c
@@ -24,13 +25,13 @@
 
 def test_init_by_array():
     rnd = Random()
-    rnd.init_by_array([1, 2, 3, 4])
+    rnd.init_by_array([r_uint(n) for n in [1, 2, 3, 4]])
     assert rnd.state[:14] == [2147483648, 1269538435, 699006892, 381364451,
             172015551, 3237099449, 3609464087, 2187366456, 654585064,
             2665903765, 3735624613, 1241943673, 2038528247, 3774211972]
     # try arrays of various sizes to test for corner cases
     for size in [N, N - 1, N + 1, N // 2, 2 * N]:
-        rnd.init_by_array(range(N))
+        rnd.init_by_array([r_uint(n) for n in range(N)])
 
 def test_jumpahead():
     rnd = Random()
@@ -47,8 +48,8 @@
     def f(x, y):
         rnd = Random(x)
         rnd.init_by_array([x, y])
-        rnd.jumpahead(y)
+        rnd.jumpahead(intmask(y))
         return rnd.genrand32(), rnd.random()
     t = Translation(f)
-    fc = t.compile_c([int, int])
-    assert fc(1, 2) == f(1, 2)
+    fc = t.compile_c([r_uint, r_uint])
+    assert fc(r_uint(1), r_uint(2)) == f(r_uint(1), r_uint(2))
diff --git a/pypy/rlib/test/test_rstacklet.py b/pypy/rlib/test/test_rstacklet.py
--- a/pypy/rlib/test/test_rstacklet.py
+++ b/pypy/rlib/test/test_rstacklet.py
@@ -1,4 +1,4 @@
-import gc
+import gc, sys
 import py
 from pypy.rpython.tool.rffi_platform import CompilationError
 try:
@@ -65,6 +65,15 @@
             self.tasks[0].withdepth(self.random.genrand32() % 50)
             assert len(self.tasks[0].lst) == 0
 
+    @here_is_a_test
+    def test_destroy(self):
+        # this used to give MemoryError in shadowstack tests
+        for i in range(100000):
+            self.status = 0
+            h = self.sthread.new(switchbackonce_callback,
+                                 rffi.cast(llmemory.Address, 321))
+            self.sthread.destroy(h)
+
     def any_alive(self):
         for task in self.tasks:
             if task.h:
@@ -228,6 +237,8 @@
         cls.old_values = Runner.config, Runner.STATUSMAX
         Runner.config = config
         Runner.STATUSMAX = 25000
+        if cls.gcrootfinder == "asmgcc" and sys.platform == "win32":
+            py.test.skip("fails with asmgcc on win32")
 
     def teardown_class(cls):
         Runner.config, Runner.STATUSMAX = cls.old_values
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -548,6 +548,9 @@
     def op_jit_marker(self, *args):
         pass
 
+    def op_jit_record_known_class(self, *args):
+        pass
+
     def op_get_exception_addr(self, *args):
         raise NotImplementedError
 
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -430,6 +430,7 @@
     'jit_force_virtual':    LLOp(canrun=True),
     'jit_is_virtual':       LLOp(canrun=True),
     'jit_force_quasi_immutable': LLOp(canrun=True),
+    'jit_record_known_class'  : LLOp(canrun=True),
     'get_exception_addr':   LLOp(),
     'get_exc_value_addr':   LLOp(),
     'do_malloc_fixedsize_clear':LLOp(canmallocgc=True),
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -548,6 +548,9 @@
 def op_jit_force_quasi_immutable(*args):
     pass
 
+def op_jit_record_known_class(x, y):
+    pass
+
 def op_get_group_member(TYPE, grpptr, memberoffset):
     from pypy.rpython.lltypesystem import llgroup
     assert isinstance(memberoffset, llgroup.GroupMemberOffset)
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -711,7 +711,7 @@
             #
             # Record the newly allocated object and its full malloced size.
             # The object is young or old depending on the argument.
-            self.rawmalloced_total_size += allocsize
+            self.rawmalloced_total_size += r_uint(allocsize)
             if can_make_young:
                 if not self.young_rawmalloced_objects:
                     self.young_rawmalloced_objects = self.AddressDict()
@@ -886,8 +886,8 @@
         #return (num_bits + (LONG_BIT - 1)) >> LONG_BIT_SHIFT
         # --- Optimized version:
         return intmask(
-            ((r_uint(length) + ((LONG_BIT << self.card_page_shift) - 1)) >>
-             (self.card_page_shift + LONG_BIT_SHIFT)))
+          ((r_uint(length) + r_uint((LONG_BIT << self.card_page_shift) - 1)) >>
+           (self.card_page_shift + LONG_BIT_SHIFT)))
 
     def card_marking_bytes_for_length(self, length):
         # --- Unoptimized version:
@@ -895,7 +895,7 @@
         #return (num_bits + 7) >> 3
         # --- Optimized version:
         return intmask(
-            ((r_uint(length) + ((8 << self.card_page_shift) - 1)) >>
+            ((r_uint(length) + r_uint((8 << self.card_page_shift) - 1)) >>
              (self.card_page_shift + 3)))
 
     def debug_check_consistency(self):
@@ -1523,7 +1523,7 @@
         llarena.arena_reserve(arena, totalsize)
         #
         size_gc_header = self.gcheaderbuilder.size_gc_header
-        self.rawmalloced_total_size += raw_malloc_usage(totalsize)
+        self.rawmalloced_total_size += r_uint(raw_malloc_usage(totalsize))
         self.old_rawmalloced_objects.append(arena + size_gc_header)
         return arena
 
@@ -1689,7 +1689,7 @@
                 allocsize += extra_words * WORD
             #
             llarena.arena_free(arena)
-            self.rawmalloced_total_size -= allocsize
+            self.rawmalloced_total_size -= r_uint(allocsize)
 
     def free_unvisited_rawmalloc_objects(self):
         list = self.old_rawmalloced_objects
diff --git a/pypy/rpython/memory/gc/minimarkpage.py b/pypy/rpython/memory/gc/minimarkpage.py
--- a/pypy/rpython/memory/gc/minimarkpage.py
+++ b/pypy/rpython/memory/gc/minimarkpage.py
@@ -149,7 +149,7 @@
         ll_assert(nsize > 0, "malloc: size is null or negative")
         ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
         ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
-        self.total_memory_used += nsize
+        self.total_memory_used += r_uint(nsize)
         #
         # Get the page to use from the size
         size_class = nsize >> WORD_POWER_2
@@ -474,7 +474,7 @@
             obj += block_size
         #
         # Update the global total size of objects.
-        self.total_memory_used += surviving * block_size
+        self.total_memory_used += r_uint(surviving * block_size)
         #
         # Return the number of surviving objects.
         return surviving
diff --git a/pypy/rpython/memory/gctransform/asmgcroot.py b/pypy/rpython/memory/gctransform/asmgcroot.py
--- a/pypy/rpython/memory/gctransform/asmgcroot.py
+++ b/pypy/rpython/memory/gctransform/asmgcroot.py
@@ -92,7 +92,6 @@
         # make a copy of the graph that will reload the values
         graph2 = copygraph(fnptr._obj.graph)
         block2 = graph2.startblock
-        block2.isstartblock = False
         block1 = Block([])
         reloadedvars = []
         for v, c_p in zip(block2.inputargs, sra):
@@ -109,7 +108,6 @@
                                                         [w], v))
             reloadedvars.append(v)
         block1.closeblock(Link(reloadedvars, block2))
-        block1.isstartblock = True
         graph2.startblock = block1
         FUNC2 = lltype.FuncType([], FUNC1.RESULT)
         fnptr2 = lltype.functionptr(FUNC2,
diff --git a/pypy/rpython/memory/gctransform/shadowstack.py b/pypy/rpython/memory/gctransform/shadowstack.py
--- a/pypy/rpython/memory/gctransform/shadowstack.py
+++ b/pypy/rpython/memory/gctransform/shadowstack.py
@@ -307,7 +307,7 @@
                   "restore_state_from: broken shadowstack")
         self.gcdata.root_stack_base = shadowstackref.base
         self.gcdata.root_stack_top  = shadowstackref.top
-        self.destroy(shadowstackref)
+        self._cleanup(shadowstackref)
 
     def start_fresh_new_state(self):
         self.gcdata.root_stack_base = self.unused_full_stack
@@ -315,6 +315,10 @@
         self.unused_full_stack = llmemory.NULL
 
     def destroy(self, shadowstackref):
+        llmemory.raw_free(shadowstackref.base)
+        self._cleanup(shadowstackref)
+
+    def _cleanup(self, shadowstackref):
         shadowstackref.base = llmemory.NULL
         shadowstackref.top = llmemory.NULL
         shadowstackref.context = llmemory.NULL
diff --git a/pypy/rpython/memory/gctransform/test/test_transform.py b/pypy/rpython/memory/gctransform/test/test_transform.py
--- a/pypy/rpython/memory/gctransform/test/test_transform.py
+++ b/pypy/rpython/memory/gctransform/test/test_transform.py
@@ -102,12 +102,12 @@
         llops.genop("gc_pop_alive", [var])
 
 
-def checkblock(block, is_borrowed):
+def checkblock(block, is_borrowed, is_start_block):
     if block.operations == ():
         # a return/exception block -- don't want to think about them
         # (even though the test passes for somewhat accidental reasons)
         return
-    if block.isstartblock:
+    if is_start_block:
         refs_in = 0
     else:
         refs_in = len([v for v in block.inputargs if isinstance(v, Variable)
@@ -167,7 +167,7 @@
     if check:
         for graph, is_borrowed in graphs_borrowed.iteritems():
             for block in graph.iterblocks():
-                checkblock(block, is_borrowed)
+                checkblock(block, is_borrowed, block is graph.startblock)
     return t, transformer
 
 def getops(graph):
diff --git a/pypy/rpython/memory/gctransform/transform.py b/pypy/rpython/memory/gctransform/transform.py
--- a/pypy/rpython/memory/gctransform/transform.py
+++ b/pypy/rpython/memory/gctransform/transform.py
@@ -263,9 +263,7 @@
         # still be empty (but let's check)
         if starts_with_empty_block(graph) and inserted_empty_startblock:
             old_startblock = graph.startblock
-            graph.startblock.isstartblock = False
             graph.startblock = graph.startblock.exits[0].target
-            graph.startblock.isstartblock = True
 
         checkgraph(graph)
 
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -1773,7 +1773,7 @@
 
         @registering(rwin32.FormatError)
         def register_rwin32_FormatError(self):
-            return extdef([rwin32.DWORD], str,
+            return extdef([lltype.Signed], str,
                           "rwin32_FormatError",
                           llimpl=rwin32.llimpl_FormatError,
                           ooimpl=rwin32.fake_FormatError)
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -12,6 +12,7 @@
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
 from pypy.rlib import rposix
+from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.annlowlevel import hlstr
@@ -442,20 +443,19 @@
 # Helper functions for win32
 
 def make_longlong(high, low):
-    return (lltype.r_longlong(high) << 32) + lltype.r_longlong(low)
+    return (rffi.r_longlong(high) << 32) + rffi.r_longlong(low)
 
 # Seconds between 1.1.1601 and 1.1.1970
-secs_between_epochs = lltype.r_longlong(11644473600)
+secs_between_epochs = rffi.r_longlong(11644473600)
 
 def FILE_TIME_to_time_t_nsec(filetime):
     ft = make_longlong(filetime.c_dwHighDateTime, filetime.c_dwLowDateTime)
     # FILETIME is in units of 100 nsec
     nsec = (ft % 10000000) * 100
     time = (ft / 10000000) - secs_between_epochs
-    return time, nsec
+    return intmask(time), intmask(nsec)
 
 def time_t_to_FILE_TIME(time, filetime):
-    ft = lltype.r_longlong((time + secs_between_epochs) * 10000000)
-    filetime.c_dwHighDateTime = lltype.r_uint(ft >> 32)
-    filetime.c_dwLowDateTime = lltype.r_uint(ft & lltype.r_uint(-1))
-
+    ft = (rffi.r_longlong(time) + secs_between_epochs) * 10000000
+    filetime.c_dwHighDateTime = rffi.r_uint(ft >> 32)
+    filetime.c_dwLowDateTime = rffi.r_uint(ft)    # masking off high bits
diff --git a/pypy/rpython/module/ll_termios.py b/pypy/rpython/module/ll_termios.py
--- a/pypy/rpython/module/ll_termios.py
+++ b/pypy/rpython/module/ll_termios.py
@@ -72,9 +72,14 @@
 
 def tcsetattr_llimpl(fd, when, attributes):
     c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
-    c_struct.c_c_iflag, c_struct.c_c_oflag, c_struct.c_c_cflag, \
-    c_struct.c_c_lflag, ispeed, ospeed, cc = attributes
     try:
+        c_struct.c_c_iflag = r_uint(attributes[0])
+        c_struct.c_c_oflag = r_uint(attributes[1])
+        c_struct.c_c_cflag = r_uint(attributes[2])
+        c_struct.c_c_lflag = r_uint(attributes[3])
+        ispeed = r_uint(attributes[4])
+        ospeed = r_uint(attributes[5])
+        cc = attributes[6]
         for i in range(NCCS):
             c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i][0]))
         if c_cfsetispeed(c_struct, ispeed) < 0:
@@ -87,8 +92,8 @@
         lltype.free(c_struct, flavor='raw')
 
 r_uint = rffi.r_uint
-register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint,
-                  r_uint, r_uint, r_uint, [str])], llimpl=tcsetattr_llimpl,
+register_external(rtermios.tcsetattr, [int, int, (int, int, int,
+                  int, int, int, [str])], llimpl=tcsetattr_llimpl,
                   export_name='termios.tcsetattr')
 
 # a bit C-c C-v code follows...
diff --git a/pypy/rpython/normalizecalls.py b/pypy/rpython/normalizecalls.py
--- a/pypy/rpython/normalizecalls.py
+++ b/pypy/rpython/normalizecalls.py
@@ -116,8 +116,6 @@
                     v = Constant(default)
                 outlist.append(v)
             newblock.closeblock(Link(outlist, oldblock))
-            oldblock.isstartblock = False
-            newblock.isstartblock = True
             graph.startblock = newblock
             for i in range(len(newdefaults)-1,-1,-1):
                 if newdefaults[i] is NODEFAULT:
@@ -171,8 +169,6 @@
             # prepare the output args of newblock and link
             outlist = inlist[:]
             newblock.closeblock(Link(outlist, oldblock))
-            oldblock.isstartblock = False
-            newblock.isstartblock = True
             graph.startblock = newblock
             # finished
             checkgraph(graph)
diff --git a/pypy/tool/nullpath.py b/pypy/tool/nullpath.py
--- a/pypy/tool/nullpath.py
+++ b/pypy/tool/nullpath.py
@@ -1,4 +1,4 @@
-import py
+import py, os
 
 class NullPyPathLocal(py.path.local):
 
@@ -6,7 +6,7 @@
         return self.__class__(py.path.local.join(self, *args))
 
     def open(self, mode):
-        return open('/dev/null', mode)
+        return open(os.devnull, mode)
 
     def __repr__(self):
         return py.path.local.__repr__(self) + ' [fake]'
diff --git a/pypy/tool/test/test_nullpath.py b/pypy/tool/test/test_nullpath.py
--- a/pypy/tool/test/test_nullpath.py
+++ b/pypy/tool/test/test_nullpath.py
@@ -1,11 +1,7 @@
-import sys
+import sys, os
 import py
 from pypy.tool.nullpath import NullPyPathLocal
 
-def setup_module():
-    if 'posix' not in sys.builtin_module_names:
-        py.test.skip('posix only')
-
 def test_nullpath(tmpdir):
     path = NullPyPathLocal(tmpdir)
     assert repr(path).endswith('[fake]')
@@ -13,4 +9,4 @@
     assert isinstance(foo_txt, NullPyPathLocal)
     #
     f = foo_txt.open('w')
-    assert f.name == '/dev/null'
+    assert f.name == os.devnull
diff --git a/pypy/translator/backendopt/constfold.py b/pypy/translator/backendopt/constfold.py
--- a/pypy/translator/backendopt/constfold.py
+++ b/pypy/translator/backendopt/constfold.py
@@ -37,8 +37,9 @@
                 except (KeyboardInterrupt, SystemExit):
                     raise
                 except Exception, e:
-                    log.WARNING('constant-folding %r:' % (spaceop,))
-                    log.WARNING('  %s: %s' % (e.__class__.__name__, e))
+                    pass   # turn off reporting these as warnings: useless
+                    #log.WARNING('constant-folding %r:' % (spaceop,))
+                    #log.WARNING('  %s: %s' % (e.__class__.__name__, e))
                 else:
                     # success in folding this space operation
                     if spaceop.opname in fixup_op_result:
diff --git a/pypy/translator/backendopt/inline.py b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -453,7 +453,6 @@
         #vars that need to be passed through the blocks of the inlined function
         linktoinlined = splitlink
         copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
-        copiedstartblock.isstartblock = False
         #find args passed to startblock of inlined function
         passon_args = []
         for arg in self.op.args[1:]:
diff --git a/pypy/translator/backendopt/mallocv.py b/pypy/translator/backendopt/mallocv.py
--- a/pypy/translator/backendopt/mallocv.py
+++ b/pypy/translator/backendopt/mallocv.py
@@ -391,7 +391,6 @@
         virtualframe = VirtualFrame(graph2.startblock, 0, nodelist)
         graphbuilder = GraphBuilder(self, graph2)
         specblock = graphbuilder.start_from_virtualframe(virtualframe)
-        specblock.isstartblock = True
         specgraph = graph2
         specgraph.name += '_mallocv'
         specgraph.startblock = specblock
diff --git a/pypy/translator/backendopt/test/test_malloc.py b/pypy/translator/backendopt/test/test_malloc.py
--- a/pypy/translator/backendopt/test/test_malloc.py
+++ b/pypy/translator/backendopt/test/test_malloc.py
@@ -50,7 +50,8 @@
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         while True:
             progress = remover.remove_mallocs_once(graph)
-            simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()))
+            simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+                                                      [graph])
             if progress and option.view:
                 t.view()
             if expected_result is not Ellipsis:
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -542,7 +542,7 @@
             mk.rule(*rule)
 
         if self.config.translation.gcrootfinder == 'asmgcc':
-            trackgcfiles = [cfile[:-2] for cfile in mk.cfiles]
+            trackgcfiles = [cfile[:cfile.rfind('.')] for cfile in mk.cfiles]
             if self.translator.platform.name == 'msvc':
                 trackgcfiles = [f for f in trackgcfiles
                                 if f.startswith(('implement', 'testing',
@@ -579,7 +579,7 @@
             if self.translator.platform.name == 'msvc':
                 lblofiles = []
                 for cfile in mk.cfiles:
-                    f = cfile[:-2]
+                    f = cfile[:cfile.rfind('.')]
                     if f in trackgcfiles:
                         ofile = '%s.lbl.obj' % (f,)
                     else:
diff --git a/pypy/translator/c/src/support.h b/pypy/translator/c/src/support.h
--- a/pypy/translator/c/src/support.h
+++ b/pypy/translator/c/src/support.h
@@ -11,6 +11,7 @@
 #endif /* MIN */
 
 #define RUNNING_ON_LLINTERP	0
+#define OP_JIT_RECORD_KNOWN_CLASS(i, c, r)  /* nothing */
 
 #define FAIL_EXCEPTION(exc, msg) \
 	{ \
diff --git a/pypy/translator/c/test/test_lltyped.py b/pypy/translator/c/test/test_lltyped.py
--- a/pypy/translator/c/test/test_lltyped.py
+++ b/pypy/translator/c/test/test_lltyped.py
@@ -476,12 +476,13 @@
         def f(n):
             result = ()
             for cls in classes:
+                nn = cls(n)
                 for OP in operators:
                     x = getmin(cls)
-                    res1 = OP(x, n)
+                    res1 = OP(x, nn)
                     result = result + (res1,)
                     x = getmax(cls)
-                    res1 = OP(x, n)
+                    res1 = OP(x, nn)
                     result = result + (res1,)
             return result
 
diff --git a/pypy/translator/c/test/test_refcount.py b/pypy/translator/c/test/test_refcount.py
--- a/pypy/translator/c/test/test_refcount.py
+++ b/pypy/translator/c/test/test_refcount.py
@@ -229,7 +229,6 @@
     graph = t.buildflowgraph(g)
     assert graph.startblock.operations == []
     graph.startblock = graph.startblock.exits[0].target
-    graph.startblock.isstartblock = True
     from pypy.objspace.flow.model import checkgraph
     checkgraph(graph)
     t._prebuilt_graphs[g] = graph
diff --git a/pypy/translator/c/test/test_standalone.py b/pypy/translator/c/test/test_standalone.py
--- a/pypy/translator/c/test/test_standalone.py
+++ b/pypy/translator/c/test/test_standalone.py
@@ -224,7 +224,7 @@
         filename = str(udir.join('test_standalone_largefile'))
         r4800000000 = r_longlong(4800000000L)
         def entry_point(argv):
-            assert str(r4800000000 + len(argv)) == '4800000003'
+            assert str(r4800000000 + r_longlong(len(argv))) == '4800000003'
             fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644)
             os.lseek(fd, r4800000000, 0)
             newpos = os.lseek(fd, 0, 1)
diff --git a/pypy/translator/c/test/test_typed.py b/pypy/translator/c/test/test_typed.py
--- a/pypy/translator/c/test/test_typed.py
+++ b/pypy/translator/c/test/test_typed.py
@@ -261,7 +261,7 @@
         f._annspecialcase_ = "specialize:argtype(0)"
         def g(n):
             if n > 0:
-                return f(r_longlong(0))
+                return intmask(f(r_longlong(0)))
             else:
                 return f(0)
 
diff --git a/pypy/translator/jvm/test/test_rarithmetic.py b/pypy/translator/jvm/test/test_rarithmetic.py
--- a/pypy/translator/jvm/test/test_rarithmetic.py
+++ b/pypy/translator/jvm/test/test_rarithmetic.py
@@ -32,7 +32,7 @@
                     cache[types] = fun
                 return cache[types](x, y)
             return f(x,y)
-        super(BaseAdaptedTest,self).binary_test(new_func, rargs)
+        super(BaseAdaptedTest,self).binary_test(new_func, rargs, translated=True)
 
 class Test_r_uint(BaseAdaptedTest, BaseTest_r_uint):
     RTYPE = ra.r_uint    
diff --git a/pypy/translator/platform/darwin.py b/pypy/translator/platform/darwin.py
--- a/pypy/translator/platform/darwin.py
+++ b/pypy/translator/platform/darwin.py
@@ -12,17 +12,10 @@
 
     so_ext = 'dylib'
 
-    # NOTE: GCC 4.2 will fail at runtime due to subtle issues, possibly
-    # related to GC roots. Using LLVM-GCC or Clang will break the build.
-    default_cc = 'gcc-4.0'
-
-    def __init__(self, cc=None):
-        if cc is None:
-            try:
-                cc = os.environ['CC']
-            except KeyError:
-                cc = self.default_cc
-        self.cc = cc
+    # NOTE: With asmgcc GCC 4.2 will fail at runtime due to subtle issues,
+    # possibly related to GC roots. Using LLVM-GCC or Clang will break the
+    # build. On Darwin asmgcc is not the default anymore, so it is fine to use
+    # whatever gcc we find on the system
 
     def _args_for_shared(self, args):
         return (list(self.shared_only)
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -179,7 +179,7 @@
         # The c compiler accepts any order of arguments, while
         # the assembler still has the old behavior that all options
         # must come first, and after the file name all options are ignored.
-        # So please be careful with the oder of parameters! ;-)
+        # So please be careful with the order of parameters! ;-)
         args = ['/nologo', '/c'] + compile_args + ['/Fo%s' % (oname,), str(cfile)]
         self._execute_c_compiler(cc, args, oname)
         return oname
@@ -265,7 +265,7 @@
                 return fpath
 
         rel_cfiles = [m.pathrel(cfile) for cfile in cfiles]
-        rel_ofiles = [rel_cfile[:-2]+'.obj' for rel_cfile in rel_cfiles]
+        rel_ofiles = [rel_cfile[:rel_cfile.rfind('.')]+'.obj' for rel_cfile in rel_cfiles]
         m.cfiles = rel_cfiles
 
         rel_includedirs = [pypyrel(incldir) for incldir in eci.include_dirs]
@@ -296,6 +296,7 @@
         rules = [
             ('all', '$(DEFAULT_TARGET)', []),
             ('.c.obj', '', '$(CC) /nologo $(CFLAGS) $(CFLAGSEXTRA) /Fo$@ /c $< $(INCLUDEDIRS)'),
+            ('.asm.obj', '', '$(MASM) /nologo /Fo$@ /c $< $(INCLUDEDIRS)'),
             ]
 
         for rule in rules:
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -397,7 +397,8 @@
 def transform_dead_op_vars(graph, translator=None):
     """Remove dead operations and variables that are passed over a link
     but not used in the target block. Input is a graph."""
-    return transform_dead_op_vars_in_blocks(list(graph.iterblocks()), translator)
+    return transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+                                            [graph], translator)
 
 # the set of operations that can safely be removed
 # (they have no side effects, at least in R-Python)
@@ -419,11 +420,19 @@
     hasattr: True,
     }
 
-def transform_dead_op_vars_in_blocks(blocks, translator=None):
+def find_start_blocks(graphs):
+    start_blocks = set()
+    for graph in graphs:
+        start_blocks.add(graph.startblock)
+    return start_blocks
+
+def transform_dead_op_vars_in_blocks(blocks, graphs, translator=None):
     """Remove dead operations and variables that are passed over a link
     but not used in the target block. Input is a set of blocks"""
     read_vars = {}  # set of variables really used
     variable_flow = {}  # map {Var: list-of-Vars-it-depends-on}
+    set_of_blocks = set(blocks)
+    start_blocks = find_start_blocks(graphs)
 
     def canremove(op, block):
         if op.opname not in CanRemove:
@@ -451,7 +460,7 @@
 
         if block.exits:
             for link in block.exits:
-                if link.target not in blocks:
+                if link.target not in set_of_blocks:
                     for arg, targetarg in zip(link.args, link.target.inputargs):
                         read_vars[arg] = True
                         read_vars[targetarg] = True
@@ -465,7 +474,7 @@
                 read_vars[arg] = True
         # an input block's inputargs should not be modified, even if some
         # of the function's input arguments are not actually used
-        if block.isstartblock:
+        if block in start_blocks:
             for arg in block.inputargs:
                 read_vars[arg] = True
 
diff --git a/pypy/translator/transform.py b/pypy/translator/transform.py
--- a/pypy/translator/transform.py
+++ b/pypy/translator/transform.py
@@ -115,7 +115,7 @@
     # to kill dead (never-followed) links,
     # which can possibly remove more variables.
     from pypy.translator.simplify import transform_dead_op_vars_in_blocks
-    transform_dead_op_vars_in_blocks(block_subset)
+    transform_dead_op_vars_in_blocks(block_subset, self.translator.graphs)
 
 def transform_dead_code(self, block_subset):
     """Remove dead code: these are the blocks that are not annotated at all
diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -42,9 +42,7 @@
     vars = [copyvar(annotator, v) for v in graph.startblock.inputargs]
     newblock = Block(vars)
     newblock.closeblock(Link(vars, graph.startblock))
-    graph.startblock.isstartblock = False
     graph.startblock = newblock
-    graph.startblock.isstartblock = True
 
 def starts_with_empty_block(graph):
     return (not graph.startblock.operations
@@ -151,9 +149,7 @@
     newop = SpaceOperation('direct_call', [c_initial_func], v_none)
     extrablock.operations = [newop]
     extrablock.closeblock(Link(args, entry_point.startblock))
-    entry_point.startblock.isstartblock = False
     entry_point.startblock = extrablock
-    entry_point.startblock.isstartblock = True
     checkgraph(entry_point)
 
 def call_final_function(translator, final_func, annhelper=None):


More information about the pypy-commit mailing list