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

ctismer noreply at buildbot.pypy.org
Sun Dec 4 01:23:41 CET 2011


Author: Christian Tismer <tismer at stackless.com>
Branch: win64-stage1
Changeset: r50101:e7ab064d5412
Date: 2011-12-04 01:22 +0100
http://bitbucket.org/pypy/pypy/changeset/e7ab064d5412/

Log:	Merge with default

diff --git a/lib_pypy/itertools.py b/lib_pypy/_itertools.py
copy from lib_pypy/itertools.py
copy to lib_pypy/_itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/_itertools.py
@@ -1,5 +1,5 @@
-# Note that PyPy contains also a built-in module 'itertools' which will
-# hide this one if compiled in.
+# Note that PyPy contains also a built-in implementation of 'itertools';
+# when translated with default options, this one is not used.
 
 """Functional tools for creating and using iterators.
 
@@ -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/lib_pypy/itertools.py b/lib_pypy/itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/itertools.py
@@ -1,670 +1,6 @@
-# Note that PyPy contains also a built-in module 'itertools' which will
-# hide this one if compiled in.
-
-"""Functional tools for creating and using iterators.
-
-Infinite iterators:
-count([n]) --> n, n+1, n+2, ...
-cycle(p) --> p0, p1, ... plast, p0, p1, ...
-repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
-
-Iterators terminating on the shortest input sequence:
-izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... 
-ifilter(pred, seq) --> elements of seq where pred(elem) is True
-ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False
-islice(seq, [start,] stop [, step]) --> elements from
-       seq[start:stop:step]
-imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...
-starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...
-tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n
-chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... 
-takewhile(pred, seq) --> seq[0], seq[1], until pred fails
-dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
-groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
-"""
-
-__all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
-           'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
-           'takewhile', 'tee']
-
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
-
-
-class chain(object):
-    """Make an iterator that returns elements from the first iterable
-    until it is exhausted, then proceeds to the next iterable, until
-    all of the iterables are exhausted. Used for treating consecutive
-    sequences as a single sequence.
-
-    Equivalent to :
-
-    def chain(*iterables):
-        for it in iterables:
-            for element in it:
-                yield element
-    """
-    def __init__(self, *iterables):
-        self._iterables_iter = iter(map(iter, iterables))
-        # little trick for the first chain.next() call
-        self._cur_iterable_iter = iter([])
-
-    def __iter__(self):
-        return self
-    
-    def next(self):
-        while True:
-            try:
-                return self._cur_iterable_iter.next()
-            except StopIteration:
-                self._cur_iterable_iter = self._iterables_iter.next()
-            except AttributeError:
-                # CPython raises a TypeError when next() is not defined
-                raise TypeError('%s has no next() method' % \
-                                (self._cur_iterable_iter))
-
-
-class compress(object):
-    def __init__(self, data, selectors):
-        self.data = iter(data)
-        self.selectors = iter(selectors)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        while True:
-            next_item = self.data.next()
-            next_selector = self.selectors.next()
-            if bool(next_selector):
-                return next_item
-
-
-class count(object):
-    """Make an iterator that returns consecutive integers starting
-    with n.  If not specified n defaults to zero. Does not currently
-    support python long integers. Often used as an argument to imap()
-    to generate consecutive data points.  Also, used with izip() to
-    add sequence numbers.
-
-    Equivalent to :
-
-    def count(n=0):
-        if not isinstance(n, int):
-            raise TypeError("%s is not a regular integer" % n)
-        while True:
-            yield n
-            n += 1
-    """
-    def __init__(self, n=0):
-        if not isinstance(n, int):
-            raise TypeError('%s is not a regular integer' % n)
-        self.times = n-1
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        self.times += 1
-        return self.times
-
-    def __repr__(self):
-        return 'count(%d)' % (self.times + 1)
-
-
-            
-class cycle(object):
-    """Make an iterator returning elements from the iterable and
-    saving a copy of each. When the iterable is exhausted, return
-    elements from the saved copy. Repeats indefinitely.
-
-    Equivalent to :
-
-    def cycle(iterable):
-        saved = []
-        for element in iterable:
-            yield element
-            saved.append(element)
-        while saved:
-            for element in saved:
-                yield element    
-    """
-    def __init__(self, iterable):
-        self._cur_iter = iter(iterable)
-        self._saved = []
-        self._must_save = True
-        
-    def __iter__(self):
-        return self
-
-    def next(self):
-        # XXX Could probably be improved
-        try:
-            next_elt = self._cur_iter.next()
-            if self._must_save:
-                self._saved.append(next_elt)
-        except StopIteration:
-            self._cur_iter = iter(self._saved)
-            next_elt = self._cur_iter.next()
-            self._must_save = False
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (self._cur_iter))
-        return next_elt
-            
-        
-class dropwhile(object):
-    """Make an iterator that drops elements from the iterable as long
-    as the predicate is true; afterwards, returns every
-    element. Note, the iterator does not produce any output until the
-    predicate is true, so it may have a lengthy start-up time.
-
-    Equivalent to :
-
-    def dropwhile(predicate, iterable):
-        iterable = iter(iterable)
-        for x in iterable:
-            if not predicate(x):
-                yield x
-                break
-        for x in iterable:
-            yield x
-    """
-    def __init__(self, predicate, iterable):
-        self._predicate = predicate
-        self._iter = iter(iterable)
-        self._dropped = False
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        try:
-            value = self._iter.next()
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (self._iter))
-        if self._dropped:
-            return value
-        while self._predicate(value):
-            value = self._iter.next()
-        self._dropped = True
-        return value
-
-class groupby(object):
-    """Make an iterator that returns consecutive keys and groups from the
-    iterable. The key is a function computing a key value for each
-    element. If not specified or is None, key defaults to an identity
-    function and returns the element unchanged. Generally, the
-    iterable needs to already be sorted on the same key function.
-
-    The returned group is itself an iterator that shares the
-    underlying iterable with groupby(). Because the source is shared,
-    when the groupby object is advanced, the previous group is no
-    longer visible. So, if that data is needed later, it should be
-    stored as a list:
-
-       groups = []
-       uniquekeys = []
-       for k, g in groupby(data, keyfunc):
-           groups.append(list(g))      # Store group iterator as a list
-           uniquekeys.append(k)
-    """    
-    def __init__(self, iterable, key=None):
-        if key is None:
-            key = lambda x: x
-        self.keyfunc = key
-        self.it = iter(iterable)
-        self.tgtkey = self.currkey = self.currvalue = xrange(0)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        while self.currkey == self.tgtkey:
-            try:
-                self.currvalue = self.it.next() # Exit on StopIteration
-            except AttributeError:
-                # CPython raises a TypeError when next() is not defined
-                raise TypeError('%s has no next() method' % \
-                                (self.it))            
-            self.currkey = self.keyfunc(self.currvalue)
-        self.tgtkey = self.currkey
-        return (self.currkey, self._grouper(self.tgtkey))
-
-    def _grouper(self, tgtkey):
-        while self.currkey == tgtkey:
-            yield self.currvalue
-            self.currvalue = self.it.next() # Exit on StopIteration
-            self.currkey = self.keyfunc(self.currvalue)
-
-
-
-class _ifilter_base(object):
-    """base class for ifilter and ifilterflase"""
-    def __init__(self, predicate, iterable):
-        # Make sure iterable *IS* iterable
-        self._iter = iter(iterable)
-        if predicate is None:
-            self._predicate = bool
-        else:
-            self._predicate = predicate
-
-    def __iter__(self):
-        return self
-    
-class ifilter(_ifilter_base):
-    """Make an iterator that filters elements from iterable returning
-    only those for which the predicate is True.  If predicate is
-    None, return the items that are true.
-
-    Equivalent to :
-
-    def ifilter:
-        if predicate is None:
-            predicate = bool
-        for x in iterable:
-            if predicate(x):
-                yield x
-    """
-    def next(self):
-        try:
-            next_elt = self._iter.next()
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (self._iter))
-        while True:
-            if self._predicate(next_elt):
-                return next_elt
-            next_elt = self._iter.next()
-
-class ifilterfalse(_ifilter_base):
-    """Make an iterator that filters elements from iterable returning
-    only those for which the predicate is False.  If predicate is
-    None, return the items that are false.
-
-    Equivalent to :
-    
-    def ifilterfalse(predicate, iterable):
-        if predicate is None:
-            predicate = bool
-        for x in iterable:
-            if not predicate(x):
-                yield x
-    """
-    def next(self):
-        try:
-            next_elt = self._iter.next()
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (self._iter))
-        while True:
-            if not self._predicate(next_elt):
-                return next_elt
-            next_elt = self._iter.next()
-             
-
-
-
-class imap(object):
-    """Make an iterator that computes the function using arguments
-    from each of the iterables. If function is set to None, then
-    imap() returns the arguments as a tuple. Like map() but stops
-    when the shortest iterable is exhausted instead of filling in
-    None for shorter iterables. The reason for the difference is that
-    infinite iterator arguments are typically an error for map()
-    (because the output is fully evaluated) but represent a common
-    and useful way of supplying arguments to imap().
-
-    Equivalent to :
-
-    def imap(function, *iterables):
-        iterables = map(iter, iterables)
-        while True:
-            args = [i.next() for i in iterables]
-            if function is None:
-                yield tuple(args)
-            else:
-                yield function(*args)
-    
-    """
-    def __init__(self, function, iterable, *other_iterables):
-        self._func = function
-        self._iters = map(iter, (iterable, ) + other_iterables)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        try:
-            args = [it.next() for it in self._iters]
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (it))
-        if self._func is None:
-            return tuple(args)
-        else:
-            return self._func(*args)
-
-
-
-class islice(object):
-    """Make an iterator that returns selected elements from the
-    iterable.  If start is non-zero, then elements from the iterable
-    are skipped until start is reached. Afterward, elements are
-    returned consecutively unless step is set higher than one which
-    results in items being skipped. If stop is None, then iteration
-    continues until the iterator is exhausted, if at all; otherwise,
-    it stops at the specified position. Unlike regular slicing,
-    islice() does not support negative values for start, stop, or
-    step. Can be used to extract related fields from data where the
-    internal structure has been flattened (for example, a multi-line
-    report may list a name field on every third line).
-    """ 
-    def __init__(self, iterable, *args):
-        s = slice(*args)
-        self.start, self.stop, self.step = s.start or 0, s.stop, s.step
-        if not isinstance(self.start, (int, long)):
-           raise ValueError("Start argument must be an integer")
-        if self.stop is not None and not isinstance(self.stop, (int,long)):
-           raise ValueError("Stop argument must be an integer or None")
-        if self.step is None:
-            self.step = 1
-        if self.start<0 or (self.stop is not None and self.stop<0
-           ) or self.step<=0:
-            raise ValueError, "indices for islice() must be positive"
-        self.it = iter(iterable)
-        self.donext = None
-        self.cnt = 0
-
-    def __iter__(self):
-        return self
-
-    def next(self): 
-        if self.donext is None:
-            try:
-                self.donext = self.it.next
-            except AttributeError:
-                raise TypeError
-        nextindex = self.start
-        if self.stop is not None and nextindex >= self.stop:
-            raise StopIteration
-        while self.cnt <= nextindex:
-            nextitem = self.donext()
-            self.cnt += 1
-        self.start += self.step 
-        return nextitem
-
-class izip(object):
-    """Make an iterator that aggregates elements from each of the
-    iterables.  Like zip() except that it returns an iterator instead
-    of a list. Used for lock-step iteration over several iterables at
-    a time.
-
-    Equivalent to :
-
-    def izip(*iterables):
-        iterables = map(iter, iterables)
-        while iterables:
-            result = [i.next() for i in iterables]
-            yield tuple(result)
-    """
-    def __init__(self, *iterables):
-        self._iterators = map(iter, iterables)
-        self._result = [None] * len(self._iterators)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        if not self._iterators:
-            raise StopIteration()
-        try:
-            return tuple([i.next() for i in self._iterators])
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % (i))
-
-
-class product(object):
-
-    def __init__(self, *args, **kw):
-        if len(kw) > 1:
-            raise TypeError("product() takes at most 1 argument (%d given)" %
-                             len(kw))
-        self.repeat = kw.get('repeat', 1)
-        self.gears = [x for x in args] * self.repeat
-        self.num_gears = len(self.gears)
-        # initialization of indicies to loop over
-        self.indicies = [(0, len(self.gears[x]))
-                         for x in range(0, self.num_gears)]
-        self.cont = True
-
-    def roll_gears(self):
-        # Starting from the end of the gear indicies work to the front
-        # incrementing the gear until the limit is reached. When the limit
-        # is reached carry operation to the next gear
-        should_carry = True
-        for n in range(0, self.num_gears):
-            nth_gear = self.num_gears - n - 1
-            if should_carry:
-                count, lim = self.indicies[nth_gear]
-                count += 1
-                if count == lim and nth_gear == 0:
-                    self.cont = False
-                if count == lim:
-                    should_carry = True
-                    count = 0
-                else:
-                    should_carry = False
-                self.indicies[nth_gear] = (count, lim)
-            else:
-                break
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        if not self.cont:
-            raise StopIteration
-        l = []
-        for x in range(0, self.num_gears):
-            index, limit = self.indicies[x]
-            l.append(self.gears[x][index])
-        self.roll_gears()
-        return tuple(l)
-
-
-class repeat(object):
-    """Make an iterator that returns object over and over again.
-    Runs indefinitely unless the times argument is specified.  Used
-    as argument to imap() for invariant parameters to the called
-    function. Also used with izip() to create an invariant part of a
-    tuple record.
-
-    Equivalent to :
-
-    def repeat(object, times=None):
-        if times is None:
-            while True:
-                yield object
-        else:
-            for i in xrange(times):
-                yield object
-    """
-    def __init__(self, obj, times=None):
-        self._obj = obj
-        if times is not None:
-            xrange(times) # Raise a TypeError
-            if times < 0:
-                times = 0
-        self._times = times
-        
-    def __iter__(self):
-        return self
-
-    def next(self):
-        # next() *need* to decrement self._times when consumed
-        if self._times is not None:
-            if self._times <= 0: 
-                raise StopIteration()
-            self._times -= 1
-        return self._obj
-
-    def __repr__(self):
-        if self._times is not None:
-            return 'repeat(%r, %r)' % (self._obj, self._times)
-        else:
-            return 'repeat(%r)' % (self._obj,)
-
-    def __len__(self):
-        if self._times == -1 or self._times is None:
-            raise TypeError("len() of uniszed object")
-        return self._times
-    
-
-class starmap(object):
-    """Make an iterator that computes the function using arguments
-    tuples obtained from the iterable. Used instead of imap() when
-    argument parameters are already grouped in tuples from a single
-    iterable (the data has been ``pre-zipped''). The difference
-    between imap() and starmap() parallels the distinction between
-    function(a,b) and function(*c).
-
-    Equivalent to :
-
-    def starmap(function, iterable):
-        iterable = iter(iterable)
-        while True:
-            yield function(*iterable.next())    
-    """
-    def __init__(self, function, iterable):
-        self._func = function
-        self._iter = iter(iterable)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        # CPython raises a TypeError when the iterator doesn't return a tuple
-        try:
-            t = self._iter.next()
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % self._iter)
-        if not isinstance(t, tuple):
-            raise TypeError("iterator must return a tuple")
-        return self._func(*t)
-
-
-
-class takewhile(object):
-    """Make an iterator that returns elements from the iterable as
-    long as the predicate is true.
-
-    Equivalent to :
-    
-    def takewhile(predicate, iterable):
-        for x in iterable:
-            if predicate(x):
-                yield x
-            else:
-                break
-    """
-    def __init__(self, predicate, iterable):
-        self._predicate = predicate
-        self._iter = iter(iterable)
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        try:
-            value = self._iter.next()
-        except AttributeError:
-            # CPython raises a TypeError when next() is not defined
-            raise TypeError('%s has no next() method' % \
-                            (self._iter))
-        if not self._predicate(value):
-            raise StopIteration()
-        return value
-
-    
-class TeeData(object):
-    """Holds cached values for TeeObjects"""
-    def __init__(self, iterator):
-        self.data = []
-        self._iter = iterator
-
-    def __getitem__(self, i):
-        # iterates until 'i' if not done yet
-        while i>= len(self.data):
-            try:
-                self.data.append( self._iter.next() )
-            except AttributeError:
-                # CPython raises a TypeError when next() is not defined
-                raise TypeError('%s has no next() method' % self._iter)
-        return self.data[i]
-
-
-class TeeObject(object):
-    """Iterables / Iterators as returned by the tee() function"""
-    def __init__(self, iterable=None, tee_data=None):
-        if tee_data:
-            self.tee_data = tee_data
-            self.pos = 0
-        # <=> Copy constructor
-        elif isinstance(iterable, TeeObject):
-            self.tee_data = iterable.tee_data
-            self.pos = iterable.pos
-        else:
-            self.tee_data = TeeData(iter(iterable))
-            self.pos = 0
-            
-    def next(self):
-        data = self.tee_data[self.pos]
-        self.pos += 1
-        return data
-    
-    def __iter__(self):
-        return self
-
-
- at builtinify
-def tee(iterable, n=2):
-    """Return n independent iterators from a single iterable.
-    Note : once tee() has made a split, the original iterable
-    should not be used anywhere else; otherwise, the iterable could get
-    advanced without the tee objects being informed.
-    
-    Note : this member of the toolkit may require significant auxiliary
-    storage (depending on how much temporary data needs to be stored).
-    In general, if one iterator is going to use most or all of the
-    data before the other iterator, it is faster to use list() instead
-    of tee()
-    
-    Equivalent to :
-    
-    def tee(iterable, n=2):
-        def gen(next, data={}, cnt=[0]):
-            for i in count():
-                if i == cnt[0]:
-                    item = data[i] = next()
-                    cnt[0] += 1
-                else:
-                    item = data.pop(i)
-                yield item
-        it = iter(iterable)
-        return tuple([gen(it.next) for i in range(n)])
-    """
-    if isinstance(iterable, TeeObject):
-        # a,b = tee(range(10)) ; c,d = tee(a) ; self.assert_(a is c)
-        return tuple([iterable] +
-        [TeeObject(tee_data=iterable.tee_data) for i in xrange(n-1)])
-    tee_data = TeeData(iter(iterable))
-    return tuple([TeeObject(tee_data=tee_data) for i in xrange(n)])
+try:
+    from __builtin_itertools import *
+    from __builtin_itertools import __doc__
+except ImportError:
+    from _itertools import *
+    from _itertools import __doc__
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/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
@@ -20,7 +20,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
@@ -1432,6 +1432,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)
@@ -1510,12 +1514,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/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
@@ -167,26 +167,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]
@@ -195,7 +191,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)
@@ -211,7 +207,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
@@ -287,15 +283,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
@@ -450,8 +446,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:
@@ -459,8 +461,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():
@@ -486,7 +491,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
@@ -149,6 +149,13 @@
             self.cpu.execute_token(loop.token)
         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)
 
@@ -422,6 +429,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
@@ -247,7 +247,7 @@
             if funcobj.random_effects_on_gcobjs:
                 return True
         except (AttributeError, lltype.DelayedPointer):
-            pass
+            return True   # better safe than sorry
         return super(RandomEffectsAnalyzer, self).analyze_external_call(
             op, seen)
 
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
@@ -210,6 +210,8 @@
     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
@@ -220,6 +222,9 @@
                 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
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
@@ -3585,7 +3585,8 @@
         self.interp_operations(f, [5], translationoptions=translationoptions)
 
 
-    def test_annotation_gives_knowledge_to_tracer(self):
+    def test_annotation_gives_class_knowledge_to_tracer(self):
+        py.test.skip("disabled")
         class Base(object):
             pass
         class A(Base):
@@ -3645,6 +3646,70 @@
         # 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):
diff --git a/pypy/module/itertools/__init__.py b/pypy/module/itertools/__init__.py
--- a/pypy/module/itertools/__init__.py
+++ b/pypy/module/itertools/__init__.py
@@ -23,6 +23,7 @@
     dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
     groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
     """
+    applevel_name = '__builtin_itertools'
 
     interpleveldefs = {
         'chain'         : 'interp_itertools.W_Chain',
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,10 +5,11 @@
     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',
@@ -16,8 +17,22 @@
         '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
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):
@@ -97,8 +97,10 @@
     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)
@@ -112,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)
@@ -135,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)
@@ -247,7 +255,7 @@
             w_rhs = self.rhs.execute(interp)
         if not isinstance(w_lhs, BaseArray):
             # scalar
-            dtype = interp.space.fromcache(W_Float64Dtype)
+            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 == '+':
@@ -264,8 +272,9 @@
             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
 
@@ -283,7 +292,7 @@
         return space.wrap(self.v)
 
     def execute(self, interp):
-        return FloatObject(self.v)
+        return interp.space.wrap(self.v)
 
 class RangeConstant(Node):
     def __init__(self, v):
@@ -291,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
@@ -315,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]) + "]"
@@ -384,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)
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,523 +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):
-    specialize.argtype(1, 2)(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):
-    specialize.argtype(1, 2)(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):
-    specialize.argtype(1)(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):
-        # XXX this won't work after translation, probably requires ovfcheck
-        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)
-    @unaryop
-    def sqrt(self, v):
-        try:
-            return math.sqrt(v)
-        except ValueError:
-            return rfloat.NAN
-
-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
-    @binop
-    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
-
-
-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
@@ -98,47 +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):
-        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 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
 # --------------------
@@ -378,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])
@@ -451,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)
@@ -462,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)
 
@@ -475,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
@@ -490,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
@@ -542,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(")")
@@ -612,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
@@ -625,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:
@@ -712,7 +677,7 @@
                 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))
 
@@ -771,14 +736,15 @@
                          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):
         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)).wrap(space)))
+        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()
@@ -814,17 +780,14 @@
         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):
     """
@@ -835,6 +798,7 @@
     _attrs_ = ["dtype", "value", "shape"]
 
     def __init__(self, dtype, value):
+        self.shape = self.strides = []
         BaseArray.__init__(self, [], 'C')
         self.dtype = dtype
         self.value = value
@@ -858,7 +822,7 @@
         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)
@@ -884,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()
@@ -1111,14 +1075,14 @@
         return 'Slice(%s)' % self.parent.debug_repr()
 
     def copy(self):
-        array = NDimArray(self.size, self.shape[:], self.find_dtype())
+        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 NDimArray(BaseArray):
+class W_NDimArray(BaseArray):
     """ A class representing contiguous array. We know that each iteration
     by say ufunc will increase the data index by one
     """
@@ -1145,11 +1109,11 @@
         return self.dtype.getitem(self.storage, iter.get_offset())
 
     def copy(self):
-        array = NDimArray(self.size, self.shape[:], self.dtype, self.order)
+        array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
         rffi.c_memcpy(
-            rffi.cast(rffi.VOIDP, array.storage),
-            rffi.cast(rffi.VOIDP, self.storage),
-            self.size * self.dtype.num_bytes
+            array.storage,
+            self.storage,
+            self.size * self.dtype.itemtype.get_element_size()
         )
         return array
 
@@ -1160,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()
@@ -1193,20 +1156,62 @@
             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)
 
@@ -1217,9 +1222,9 @@
     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),
@@ -1308,10 +1313,10 @@
 
     def descr_next(self, space):
         if self.iter.done():
-            raise OperationError(space.w_StopIteration, space.wrap(''))
+            raise OperationError(space.w_StopIteration, space.w_None)
         result = self.eval(self.iter)
         self.iter = self.iter.next(self.shapelen)
-        return result.wrap(space)
+        return result
 
     def descr_iter(self):
         return self
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)
 
@@ -338,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/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,7 +178,7 @@
         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("""
@@ -185,7 +188,7 @@
         a[::3] = b
         a -> 3
         """)
-        assert interp.results[0].value.val == 5
+        assert interp.results[0].value == 5
 
 
     def test_slice2(self):
@@ -196,14 +199,14 @@
         b = s1 + s2
         b -> 3
         """)
-        assert interp.results[0].value.val == 15
+        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("""
@@ -211,7 +214,7 @@
         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("""
@@ -220,7 +223,7 @@
         b[:] = a + a
         b -> 3
         """)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
 
     def test_set_slice2(self):
         interp = self.run("""
@@ -231,4 +234,4 @@
         a[0:30:3] = c
         a -> 3
         """)
-        assert interp.results[0].value.val == 11        
+        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
@@ -31,7 +31,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"
@@ -45,13 +45,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 is_valid_int(a[0])
+        assert isinstance(a[0], int64)
         b = a.copy()
-        assert is_valid_int(b[0])
+        assert isinstance(b[0], int64)
 
         a = array([0, 1, 2, 3], dtype=bool)
         assert a[0] is False_
@@ -73,17 +73,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 is_valid_int(a[i])
+            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 is_valid_int(a[i])
+            assert isinstance(a[i], int64)
             assert a[1] == 1
 
     def test_overflow(self):
@@ -166,3 +166,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,7 +1,7 @@
 
 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
@@ -28,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]
@@ -58,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]
@@ -78,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)])
@@ -96,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)])
@@ -114,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]
@@ -122,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)])
@@ -139,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)])
@@ -160,6 +160,21 @@
 
 
 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))
@@ -359,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
 
@@ -709,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)
@@ -719,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
@@ -1008,10 +1027,10 @@
         b = a[0].copy()
         assert (b == zeros(10)).all()
 
-class AppTestSupport(object):
+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):
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)
 
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,11 +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,\
-     BaseArray
+from pypy.module.micronumpy.interp_numarray import (W_NDimArray, NDimSlice,
+     BaseArray)
 from pypy.rlib.nonconst import NonConstant
 from pypy.rpython.annlowlevel import llstr, hlstr
 
@@ -48,17 +48,15 @@
         def f(i):
             interp = InterpreterState(codes[i])
             interp.run(space)
-            res = interp.results[-1]
-            assert isinstance(res, BaseArray)
-            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],
@@ -80,9 +78,9 @@
 
     def test_add(self):
         result = self.run("add")
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
-                          'setarrayitem_raw': 1, 'int_add': 3,
-                          'int_ge': 1, 'guard_false': 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})
         assert result == 3 + 3
 
     def define_float_add():
@@ -94,9 +92,9 @@
     def test_floatadd(self):
         result = self.run("float_add")
         assert result == 3 + 3
-        self.check_simple_loop({"getarrayitem_raw": 1, "float_add": 1,
-                          "setarrayitem_raw": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 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_simple_loop({"getarrayitem_raw": 2, "float_add": 2,
-                          "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        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,9 +123,9 @@
         for i in range(30):
             expected *= i * 2
         assert result == expected
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        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")
@@ -138,9 +136,9 @@
         max(b)
         """)
         assert result == 256
-        self.check_simple_loop({"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")
@@ -151,9 +149,9 @@
         min(b)
         """)
         assert result == -24
-        self.check_simple_loop({"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 define_any():
         return """
@@ -166,10 +164,10 @@
     def test_any(self):
         result = self.run("any")
         assert result == 1
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_ne": 1, "int_add": 2,
-                          "int_ge": 1, "jump": 1,
-                          "guard_false": 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 """
@@ -188,10 +186,10 @@
         # sure it was optimized correctly.
         # XXX the comment above is wrong now.  We need preferrably a way to
         # count the two loops separately
-        self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+        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': 4, '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():
@@ -205,10 +203,9 @@
     def test_ufunc(self):
         result = self.run("ufunc")
         assert result == -6
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1, "float_neg": 1,
-                          "setarrayitem_raw": 1, "int_add": 3,
-                          "int_ge": 1, "guard_false": 1, "jump": 1,
-        })
+        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 """
@@ -246,9 +243,9 @@
     def test_slice(self):
         result = self.run("slice")
         assert result == 18
-        self.check_simple_loop({'getarrayitem_raw': 2,
+        self.check_simple_loop({'getinteriorfield_raw': 2,
                                 'float_add': 1,
-                                'setarrayitem_raw': 1,
+                                'setinteriorfield_raw': 1,
                                 'int_add': 3,
                                 'int_ge': 1, 'guard_false': 1,
                                 'jump': 1})
@@ -265,8 +262,8 @@
     def test_slice2(self):
         result = self.run("slice2")
         assert result == 15
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
-                                'setarrayitem_raw': 1, 'int_add': 3,
+        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():
@@ -279,11 +276,11 @@
     def test_multidim(self):
         result = self.run('multidim')
         assert result == 8
-        self.check_simple_loop({'float_add': 1, 'getarrayitem_raw': 2,
-                          'guard_false': 1, 'int_add': 3, 'int_ge': 1,
-                          'jump': 1, 'setarrayitem_raw': 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 """
@@ -329,18 +326,18 @@
         result = self.run("setslice")
         assert result == 11.0
         self.check_loop_count(1)
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add' : 1,
-                                'setarrayitem_raw': 1, 'int_add': 3,
+        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)
+        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 "
@@ -355,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/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/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -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
@@ -416,6 +416,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:
@@ -425,6 +429,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:
@@ -433,4 +438,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/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
@@ -555,6 +555,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/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) \
 	{ \


More information about the pypy-commit mailing list