[pypy-commit] pypy default: merge

cocoatomo noreply at buildbot.pypy.org
Fri Jan 20 17:26:34 CET 2012


Author: cocoatomo <cocoatomo77 at gmail.com>
Branch: 
Changeset: r51555:3f7ae53430c4
Date: 2012-01-20 14:06 +0900
http://bitbucket.org/pypy/pypy/changeset/3f7ae53430c4/

Log:	merge

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -2,6 +2,9 @@
 *.py[co]
 *~
 .*.swp
+.idea
+.project
+.pydevproject
 
 syntax: regexp
 ^testresult$
diff --git a/lib_pypy/numpypy/__init__.py b/lib_pypy/numpypy/__init__.py
--- a/lib_pypy/numpypy/__init__.py
+++ b/lib_pypy/numpypy/__init__.py
@@ -1,2 +1,2 @@
 from _numpypy import *
-from .fromnumeric import *
+from .core import *
diff --git a/lib_pypy/numpypy/core/__init__.py b/lib_pypy/numpypy/core/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/__init__.py
@@ -0,0 +1,1 @@
+from .fromnumeric import *
diff --git a/lib_pypy/numpypy/fromnumeric.py b/lib_pypy/numpypy/core/fromnumeric.py
rename from lib_pypy/numpypy/fromnumeric.py
rename to lib_pypy/numpypy/core/fromnumeric.py
--- a/lib_pypy/numpypy/fromnumeric.py
+++ b/lib_pypy/numpypy/core/fromnumeric.py
@@ -85,7 +85,7 @@
     array([4, 3, 6])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 # not deprecated --- copy if necessary, view otherwise
@@ -273,7 +273,7 @@
             [-1, -2, -3, -4, -5]]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def repeat(a, repeats, axis=None):
@@ -315,7 +315,7 @@
            [3, 4]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def put(a, ind, v, mode='raise'):
@@ -366,7 +366,7 @@
     array([ 0,  1,  2,  3, -5])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def swapaxes(a, axis1, axis2):
@@ -410,7 +410,7 @@
             [3, 7]]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def transpose(a, axes=None):
@@ -451,8 +451,11 @@
     (2, 1, 3)
 
     """
-    raise NotImplemented('Waiting on interp level method')
-
+    if axes is not None:
+        raise NotImplementedError('No "axes" arg yet.')
+    if not hasattr(a, 'T'):
+        a = numpypy.array(a)
+    return a.T
 
 def sort(a, axis=-1, kind='quicksort', order=None):
     """
@@ -553,7 +556,7 @@
           dtype=[('name', '|S10'), ('height', '<f8'), ('age', '<i4')])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def argsort(a, axis=-1, kind='quicksort', order=None):
@@ -634,7 +637,7 @@
     array([0, 1])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def argmax(a, axis=None):
@@ -753,7 +756,7 @@
     array([0, 5, 1, 2])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def resize(a, new_shape):
@@ -794,7 +797,7 @@
            [0, 1, 2, 3]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def squeeze(a):
@@ -821,7 +824,7 @@
     (3,)
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def diagonal(a, offset=0, axis1=0, axis2=1):
@@ -905,7 +908,7 @@
            [5, 7]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):
@@ -964,7 +967,7 @@
     (2, 3)
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 def ravel(a, order='C'):
     """
@@ -1048,7 +1051,7 @@
     array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def nonzero(a):
@@ -1124,7 +1127,7 @@
     (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def shape(a):
@@ -1229,7 +1232,7 @@
     array([2])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def clip(a, a_min, a_max, out=None):
@@ -1282,7 +1285,7 @@
     array([3, 4, 2, 3, 4, 5, 6, 7, 8, 8])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def sum(a, axis=None, dtype=None, out=None):
@@ -1365,7 +1368,7 @@
     prod : equivalent function; see for details.
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def sometrue(a, axis=None, out=None):
@@ -1590,7 +1593,7 @@
            [ 4,  9, 15]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def cumproduct(a, axis=None, dtype=None, out=None):
@@ -1603,7 +1606,7 @@
     cumprod : equivalent function; see for details.
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def ptp(a, axis=None, out=None):
@@ -1644,7 +1647,7 @@
     array([1, 1])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def amax(a, axis=None, out=None):
@@ -1873,7 +1876,7 @@
     True
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def cumprod(a, axis=None, dtype=None, out=None):
@@ -1936,7 +1939,7 @@
            [  4,  20, 120]])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def ndim(a):
@@ -2054,7 +2057,7 @@
     2
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def around(a, decimals=0, out=None):
@@ -2123,7 +2126,7 @@
     array([ 0,  0,  0, 10])
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def round_(a, decimals=0, out=None):
@@ -2137,7 +2140,7 @@
     around : equivalent function
 
     """
-    raise NotImplemented('Waiting on interp level method')
+    raise NotImplementedError('Waiting on interp level method')
 
 
 def mean(a, axis=None, dtype=None, out=None):
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -340,7 +340,7 @@
                    requires=[("objspace.std.builtinshortcut", True)]),
         BoolOption("withidentitydict",
                    "track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
-                   default=True),
+                   default=False),
      ]),
 ])
 
@@ -370,6 +370,7 @@
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)
         config.objspace.std.suggest(withspecialisedtuple=True)
+        config.objspace.std.suggest(withidentitydict=True)
         #if not IS_64_BITS:
         #    config.objspace.std.suggest(withsmalllong=True)
 
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1872,6 +1872,7 @@
                 values.append(descr)
                 values.append(self.cpu.get_latest_value_int(0))
                 values.append(self.cpu.get_latest_value_int(1))
+                values.append(token)
 
         FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Void)
         func_ptr = llhelper(lltype.Ptr(FUNC), maybe_force)
@@ -1902,7 +1903,8 @@
         assert fail.identifier == 1
         assert self.cpu.get_latest_value_int(0) == 1
         assert self.cpu.get_latest_value_int(1) == 10
-        assert values == [faildescr, 1, 10]
+        token = self.cpu.get_latest_force_token()
+        assert values == [faildescr, 1, 10, token]
 
     def test_force_operations_returning_int(self):
         values = []
@@ -1911,6 +1913,7 @@
                self.cpu.force(token)
                values.append(self.cpu.get_latest_value_int(0))
                values.append(self.cpu.get_latest_value_int(2))
+               values.append(token)
             return 42
 
         FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
@@ -1944,7 +1947,8 @@
         assert self.cpu.get_latest_value_int(0) == 1
         assert self.cpu.get_latest_value_int(1) == 42
         assert self.cpu.get_latest_value_int(2) == 10
-        assert values == [1, 10]
+        token = self.cpu.get_latest_force_token()
+        assert values == [1, 10, token]
 
     def test_force_operations_returning_float(self):
         values = []
@@ -1953,6 +1957,7 @@
                self.cpu.force(token)
                values.append(self.cpu.get_latest_value_int(0))
                values.append(self.cpu.get_latest_value_int(2))
+               values.append(token)
             return 42.5
 
         FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Float)
@@ -1988,7 +1993,8 @@
         x = self.cpu.get_latest_value_float(1)
         assert longlong.getrealfloat(x) == 42.5
         assert self.cpu.get_latest_value_int(2) == 10
-        assert values == [1, 10]
+        token = self.cpu.get_latest_force_token()
+        assert values == [1, 10, token]
 
     def test_call_to_c_function(self):
         from pypy.rlib.libffi import CDLL, types, ArgChain, FUNCFLAG_CDECL
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -1003,16 +1003,16 @@
         return insns
 
     def check_simple_loop(self, expected=None, **check):
-        # Usefull in the simplest case when we have only one trace ending with
-        # a jump back to itself and possibly a few bridges ending with finnish.
-        # Only the operations within the loop formed by that single jump will
-        # be counted.
+        """ Usefull in the simplest case when we have only one trace ending with
+        a jump back to itself and possibly a few bridges.
+        Only the operations within the loop formed by that single jump will
+        be counted.
+        """
         loops = self.get_all_loops()
         assert len(loops) == 1
         loop = loops[0]
         jumpop = loop.operations[-1]
         assert jumpop.getopnum() == rop.JUMP
-        assert self.check_resops(jump=1)
         labels = [op for op in loop.operations if op.getopnum() == rop.LABEL]
         targets = [op._descr_wref() for op in labels]
         assert None not in targets # TargetToken was freed, give up
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
@@ -2629,6 +2629,38 @@
         self.check_jitcell_token_count(1)
         self.check_target_token_count(5)
 
+    def test_max_unroll_loops(self):
+        from pypy.jit.metainterp.optimize import InvalidLoop
+        from pypy.jit.metainterp import optimizeopt
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i'])
+        #
+        def f(n, limit):
+            set_param(myjitdriver, 'threshold', 5)
+            set_param(myjitdriver, 'max_unroll_loops', limit)
+            i = 0
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i)
+                print i
+                i += 1
+            return i
+        #
+        def my_optimize_trace(*args, **kwds):
+            raise InvalidLoop
+        old_optimize_trace = optimizeopt.optimize_trace
+        optimizeopt.optimize_trace = my_optimize_trace
+        try:
+            res = self.meta_interp(f, [23, 4])
+            assert res == 23
+            self.check_trace_count(0)
+            self.check_aborted_count(3)
+            #
+            res = self.meta_interp(f, [23, 20])
+            assert res == 23
+            self.check_trace_count(0)
+            self.check_aborted_count(2)
+        finally:
+            optimizeopt.optimize_trace = old_optimize_trace
+
     def test_retrace_limit_with_extra_guards(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a',
                                                      'node'])
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -108,6 +108,10 @@
     w_result = state.codec_search_cache.get(normalized_encoding, None)
     if w_result is not None:
         return w_result
+    return _lookup_codec_loop(space, encoding, normalized_encoding)
+
+def _lookup_codec_loop(space, encoding, normalized_encoding):
+    state = space.fromcache(CodecState)
     if state.codec_need_encodings:
         w_import = space.getattr(space.builtin, space.wrap("__import__"))
         # registers new codecs
diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -588,10 +588,18 @@
         raises(UnicodeDecodeError, '+3ADYAA-'.decode, 'utf-7')
 
     def test_utf_16_encode_decode(self):
-        import codecs
+        import codecs, sys
         x = u'123abc'
-        assert codecs.getencoder('utf-16')(x) == ('\xff\xfe1\x002\x003\x00a\x00b\x00c\x00', 6)
-        assert codecs.getdecoder('utf-16')('\xff\xfe1\x002\x003\x00a\x00b\x00c\x00') == (x, 14)
+        if sys.byteorder == 'big':
+            assert codecs.getencoder('utf-16')(x) == (
+                    '\xfe\xff\x001\x002\x003\x00a\x00b\x00c', 6)
+            assert codecs.getdecoder('utf-16')(
+                    '\xfe\xff\x001\x002\x003\x00a\x00b\x00c') == (x, 14)
+        else:
+            assert codecs.getencoder('utf-16')(x) == (
+                    '\xff\xfe1\x002\x003\x00a\x00b\x00c\x00', 6)
+            assert codecs.getdecoder('utf-16')(
+                    '\xff\xfe1\x002\x003\x00a\x00b\x00c\x00') == (x, 14)
 
     def test_unicode_escape(self):        
         assert u'\\'.encode('unicode-escape') == '\\\\'
diff --git a/pypy/module/_codecs/test/test_ztranslation.py b/pypy/module/_codecs/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_codecs/test/test_ztranslation.py
@@ -0,0 +1,5 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+
+def test__codecs_translates():
+    checkmodule('_codecs')
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
 #define PY_VERSION		"2.7.1"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "1.7.1"
+#define PYPY_VERSION "1.8.1"
 
 /* Subversion Revision number of this file (not of the repository).
  * Empty since Mercurial migration. */
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
@@ -70,6 +70,7 @@
         ("exp", "exp"),
         ("fabs", "fabs"),
         ("floor", "floor"),
+        ("ceil", "ceil"),
         ("greater", "greater"),
         ("greater_equal", "greater_equal"),
         ("less", "less"),
@@ -90,7 +91,6 @@
 
     appleveldefs = {
         'average': 'app_numpy.average',
-        'mean': 'app_numpy.mean',
         'sum': 'app_numpy.sum',
         'min': 'app_numpy.min',
         'identity': 'app_numpy.identity',
@@ -99,5 +99,4 @@
         'e': 'app_numpy.e',
         'pi': 'app_numpy.pi',
         'arange': 'app_numpy.arange',
-        'reshape': 'app_numpy.reshape',
     }
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -11,33 +11,54 @@
 def average(a):
     # This implements a weighted average, for now we don't implement the
     # weighting, just the average part!
-    return mean(a)
+    if not hasattr(a, "mean"):
+        a = _numpypy.array(a)
+    return a.mean()
 
 def identity(n, dtype=None):
-    a = _numpypy.zeros((n,n), dtype=dtype)
+    a = _numpypy.zeros((n, n), dtype=dtype)
     for i in range(n):
         a[i][i] = 1
     return a
 
-def mean(a):
-    if not hasattr(a, "mean"):
-        a = _numpypy.array(a)
-    return a.mean()
+def sum(a,axis=None):
+    '''sum(a, axis=None)
+    Sum of array elements over a given axis.
 
-def sum(a):
+    Parameters
+    ----------
+    a : array_like
+        Elements to sum.
+    axis : integer, optional
+        Axis over which the sum is taken. By default `axis` is None,
+        and all elements are summed.
+
+    Returns
+    -------
+    sum_along_axis : ndarray
+        An array with the same shape as `a`, with the specified
+        axis removed.   If `a` is a 0-d array, or if `axis` is None, a scalar
+        is returned.  If an output array is specified, a reference to
+        `out` is returned.
+
+    See Also
+    --------
+    ndarray.sum : Equivalent method.
+    '''
+    # TODO: add to doc (once it's implemented): cumsum : Cumulative sum of array elements.
     if not hasattr(a, "sum"):
         a = _numpypy.array(a)
-    return a.sum()
+    return a.sum(axis)
 
-def min(a):
+def min(a, axis=None):
     if not hasattr(a, "min"):
         a = _numpypy.array(a)
-    return a.min()
+    return a.min(axis)
 
-def max(a):
+def max(a, axis=None):
     if not hasattr(a, "max"):
         a = _numpypy.array(a)
-    return a.max()
+    return a.max(axis)
 
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
@@ -55,40 +76,3 @@
         arr[j] = i
         i += step
     return arr
-
-
-def reshape(a, shape):
-    '''reshape(a, newshape)
-    Gives a new shape to an array without changing its data.
-
-    Parameters
-    ----------
-    a : array_like
-        Array to be reshaped.
-    newshape : int or tuple of ints
-        The new shape should be compatible with the original shape. If
-        an integer, then the result will be a 1-D array of that length.
-        One shape dimension can be -1. In this case, the value is inferred
-        from the length of the array and remaining dimensions.
-
-    Returns
-    -------
-    reshaped_array : ndarray
-        This will be a new view object if possible; otherwise, it will
-        be a copy.
-
-
-    See Also
-    --------
-    ndarray.reshape : Equivalent method.
-
-    Notes
-    -----
-
-    It is not always possible to change the shape of an array without
-    copying the data. If you want an error to be raise if the data is copied,
-    you should assign the new shape to the shape attribute of the array
-'''
-    if not hasattr(a, 'reshape'):
-        a = _numpypy.array(a)
-    return a.reshape(shape)
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
@@ -372,13 +372,17 @@
 
     def execute(self, interp):
         if self.name in SINGLE_ARG_FUNCTIONS:
-            if len(self.args) != 1:
+            if len(self.args) != 1 and self.name != 'sum':
                 raise ArgumentMismatch
             arr = self.args[0].execute(interp)
             if not isinstance(arr, BaseArray):
                 raise ArgumentNotAnArray
             if self.name == "sum":
-                w_res = arr.descr_sum(interp.space)
+                if len(self.args)>1:
+                    w_res = arr.descr_sum(interp.space,
+                                          self.args[1].execute(interp))
+                else:
+                    w_res = arr.descr_sum(interp.space)
             elif self.name == "prod":
                 w_res = arr.descr_prod(interp.space)
             elif self.name == "max":
@@ -416,7 +420,7 @@
     ('\]', 'array_right'),
     ('(->)|[\+\-\*\/]', 'operator'),
     ('=', 'assign'),
-    (',', 'coma'),
+    (',', 'comma'),
     ('\|', 'pipe'),
     ('\(', 'paren_left'),
     ('\)', 'paren_right'),
@@ -504,7 +508,7 @@
         return SliceConstant(start, stop, step)
 
 
-    def parse_expression(self, tokens):
+    def parse_expression(self, tokens, accept_comma=False):
         stack = []
         while tokens.remaining():
             token = tokens.pop()
@@ -524,9 +528,13 @@
                 stack.append(RangeConstant(tokens.pop().v))
                 end = tokens.pop()
                 assert end.name == 'pipe'
+            elif accept_comma and token.name == 'comma':
+                continue
             else:
                 tokens.push()
                 break
+        if accept_comma:
+            return stack
         stack.reverse()
         lhs = stack.pop()
         while stack:
@@ -540,7 +548,7 @@
         args = []
         tokens.pop() # lparen
         while tokens.get(0).name != 'paren_right':
-            args.append(self.parse_expression(tokens))
+            args += self.parse_expression(tokens, accept_comma=True)
         return FunctionCall(name, args)
 
     def parse_array_const(self, tokens):
@@ -556,7 +564,7 @@
             token = tokens.pop()
             if token.name == 'array_right':
                 return elems
-            assert token.name == 'coma'
+            assert token.name == 'comma'
 
     def parse_statement(self, tokens):
         if (tokens.get(0).name == 'identifier' and
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
@@ -20,7 +20,7 @@
 class W_Dtype(Wrappable):
     _immutable_fields_ = ["itemtype", "num", "kind"]
 
-    def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[]):
+    def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[], aliases=[]):
         self.itemtype = itemtype
         self.num = num
         self.kind = kind
@@ -28,6 +28,7 @@
         self.char = char
         self.w_box_type = w_box_type
         self.alternate_constructors = alternate_constructors
+        self.aliases = aliases
 
     def malloc(self, length):
         # XXX find out why test_zjit explodes with tracking of allocations
@@ -62,7 +63,7 @@
         elif space.isinstance_w(w_dtype, space.w_str):
             name = space.str_w(w_dtype)
             for dtype in cache.builtin_dtypes:
-                if dtype.name == name or dtype.char == name:
+                if dtype.name == name or dtype.char == name or name in dtype.aliases:
                     return dtype
         else:
             for dtype in cache.builtin_dtypes:
@@ -107,7 +108,7 @@
             kind=BOOLLTR,
             name="bool",
             char="?",
-            w_box_type = space.gettypefor(interp_boxes.W_BoolBox),
+            w_box_type=space.gettypefor(interp_boxes.W_BoolBox),
             alternate_constructors=[space.w_bool],
         )
         self.w_int8dtype = W_Dtype(
@@ -116,7 +117,7 @@
             kind=SIGNEDLTR,
             name="int8",
             char="b",
-            w_box_type = space.gettypefor(interp_boxes.W_Int8Box)
+            w_box_type=space.gettypefor(interp_boxes.W_Int8Box)
         )
         self.w_uint8dtype = W_Dtype(
             types.UInt8(),
@@ -124,7 +125,7 @@
             kind=UNSIGNEDLTR,
             name="uint8",
             char="B",
-            w_box_type = space.gettypefor(interp_boxes.W_UInt8Box),
+            w_box_type=space.gettypefor(interp_boxes.W_UInt8Box),
         )
         self.w_int16dtype = W_Dtype(
             types.Int16(),
@@ -132,7 +133,7 @@
             kind=SIGNEDLTR,
             name="int16",
             char="h",
-            w_box_type = space.gettypefor(interp_boxes.W_Int16Box),
+            w_box_type=space.gettypefor(interp_boxes.W_Int16Box),
         )
         self.w_uint16dtype = W_Dtype(
             types.UInt16(),
@@ -140,7 +141,7 @@
             kind=UNSIGNEDLTR,
             name="uint16",
             char="H",
-            w_box_type = space.gettypefor(interp_boxes.W_UInt16Box),
+            w_box_type=space.gettypefor(interp_boxes.W_UInt16Box),
         )
         self.w_int32dtype = W_Dtype(
             types.Int32(),
@@ -148,7 +149,7 @@
             kind=SIGNEDLTR,
             name="int32",
             char="i",
-             w_box_type = space.gettypefor(interp_boxes.W_Int32Box),
+            w_box_type=space.gettypefor(interp_boxes.W_Int32Box),
        )
         self.w_uint32dtype = W_Dtype(
             types.UInt32(),
@@ -156,7 +157,7 @@
             kind=UNSIGNEDLTR,
             name="uint32",
             char="I",
-            w_box_type = space.gettypefor(interp_boxes.W_UInt32Box),
+            w_box_type=space.gettypefor(interp_boxes.W_UInt32Box),
         )
         if LONG_BIT == 32:
             name = "int32"
@@ -168,7 +169,7 @@
             kind=SIGNEDLTR,
             name=name,
             char="l",
-            w_box_type = space.gettypefor(interp_boxes.W_LongBox),
+            w_box_type=space.gettypefor(interp_boxes.W_LongBox),
             alternate_constructors=[space.w_int],
         )
         self.w_ulongdtype = W_Dtype(
@@ -177,7 +178,7 @@
             kind=UNSIGNEDLTR,
             name="u" + name,
             char="L",
-            w_box_type = space.gettypefor(interp_boxes.W_ULongBox),
+            w_box_type=space.gettypefor(interp_boxes.W_ULongBox),
         )
         self.w_int64dtype = W_Dtype(
             types.Int64(),
@@ -185,7 +186,7 @@
             kind=SIGNEDLTR,
             name="int64",
             char="q",
-            w_box_type = space.gettypefor(interp_boxes.W_Int64Box),
+            w_box_type=space.gettypefor(interp_boxes.W_Int64Box),
             alternate_constructors=[space.w_long],
         )
         self.w_uint64dtype = W_Dtype(
@@ -194,7 +195,7 @@
             kind=UNSIGNEDLTR,
             name="uint64",
             char="Q",
-            w_box_type = space.gettypefor(interp_boxes.W_UInt64Box),
+            w_box_type=space.gettypefor(interp_boxes.W_UInt64Box),
         )
         self.w_float32dtype = W_Dtype(
             types.Float32(),
@@ -202,7 +203,7 @@
             kind=FLOATINGLTR,
             name="float32",
             char="f",
-            w_box_type = space.gettypefor(interp_boxes.W_Float32Box),
+            w_box_type=space.gettypefor(interp_boxes.W_Float32Box),
         )
         self.w_float64dtype = W_Dtype(
             types.Float64(),
@@ -212,6 +213,7 @@
             char="d",
             w_box_type = space.gettypefor(interp_boxes.W_Float64Box),
             alternate_constructors=[space.w_float],
+            aliases=["float"],
         )
 
         self.builtin_dtypes = [
diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py
--- a/pypy/module/micronumpy/interp_iter.py
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -1,19 +1,20 @@
 
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import instantiate
-from pypy.module.micronumpy.strides import calculate_broadcast_strides
+from pypy.module.micronumpy.strides import calculate_broadcast_strides,\
+     calculate_slice_strides
 
-# Iterators for arrays
-# --------------------
-# all those iterators with the exception of BroadcastIterator iterate over the
-# entire array in C order (the last index changes the fastest). This will
-# yield all elements. Views iterate over indices and look towards strides and
-# backstrides to find the correct position. Notably the offset between
-# x[..., i + 1] and x[..., i] will be strides[-1]. Offset between
-# x[..., k + 1, 0] and x[..., k, i_max] will be backstrides[-2] etc.
+class BaseTransform(object):
+    pass
 
-# BroadcastIterator works like that, but for indexes that don't change source
-# in the original array, strides[i] == backstrides[i] == 0
+class ViewTransform(BaseTransform):
+    def __init__(self, chunks):
+        # 4-tuple specifying slicing
+        self.chunks = chunks
+
+class BroadcastTransform(BaseTransform):
+    def __init__(self, res_shape):
+        self.res_shape = res_shape
 
 class BaseIterator(object):
     def next(self, shapelen):
@@ -22,6 +23,15 @@
     def done(self):
         raise NotImplementedError
 
+    def apply_transformations(self, arr, transformations):
+        v = self
+        for transform in transformations:
+            v = v.transform(arr, transform)
+        return v
+
+    def transform(self, arr, t):
+        raise NotImplementedError
+
 class ArrayIterator(BaseIterator):
     def __init__(self, size):
         self.offset = 0
@@ -36,6 +46,10 @@
     def done(self):
         return self.offset >= self.size
 
+    def transform(self, arr, t):
+        return ViewIterator(arr.start, arr.strides, arr.backstrides,
+                            arr.shape).transform(arr, t)
+
 class OneDimIterator(BaseIterator):
     def __init__(self, start, step, stop):
         self.offset = start
@@ -52,26 +66,29 @@
     def done(self):
         return self.offset == self.size
 
-def view_iter_from_arr(arr):
-    return ViewIterator(arr.start, arr.strides, arr.backstrides, arr.shape)
-
 class ViewIterator(BaseIterator):
-    def __init__(self, start, strides, backstrides, shape, res_shape=None):
+    def __init__(self, start, strides, backstrides, shape):
         self.offset  = start
         self._done   = False
-        if res_shape is not None and res_shape != shape:
-            r = calculate_broadcast_strides(strides, backstrides,
-                                            shape, res_shape)
-            self.strides, self.backstrides = r
-            self.res_shape = res_shape
-        else:
-            self.strides = strides
-            self.backstrides = backstrides
-            self.res_shape = shape
+        self.strides = strides
+        self.backstrides = backstrides
+        self.res_shape = shape
         self.indices = [0] * len(self.res_shape)
 
+    def transform(self, arr, t):
+        if isinstance(t, BroadcastTransform):
+            r = calculate_broadcast_strides(self.strides, self.backstrides,
+                                            self.res_shape, t.res_shape)
+            return ViewIterator(self.offset, r[0], r[1], t.res_shape)
+        elif isinstance(t, ViewTransform):
+            r = calculate_slice_strides(self.res_shape, self.offset,
+                                        self.strides,
+                                        self.backstrides, t.chunks)
+            return ViewIterator(r[1], r[2], r[3], r[0])
+
     @jit.unroll_safe
     def next(self, shapelen):
+        shapelen = jit.promote(len(self.res_shape))
         offset = self.offset
         indices = [0] * shapelen
         for i in range(shapelen):
@@ -96,6 +113,13 @@
         res._done = done
         return res
 
+    def apply_transformations(self, arr, transformations):
+        v = BaseIterator.apply_transformations(self, arr, transformations)
+        if len(arr.shape) == 1:
+            return OneDimIterator(self.offset, self.strides[0],
+                                  self.res_shape[0])
+        return v
+
     def done(self):
         return self._done
 
@@ -103,11 +127,59 @@
     def next(self, shapelen):
         return self
 
+    def transform(self, arr, t):
+        pass
+
+class AxisIterator(BaseIterator):
+    def __init__(self, start, dim, shape, strides, backstrides):
+        self.res_shape = shape[:]
+        self.strides = strides[:dim] + [0] + strides[dim:]
+        self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
+        self.first_line = True
+        self.indices = [0] * len(shape)
+        self._done = False
+        self.offset = start
+        self.dim = dim
+
+    @jit.unroll_safe
+    def next(self, shapelen):
+        offset = self.offset
+        first_line = self.first_line
+        indices = [0] * shapelen
+        for i in range(shapelen):
+            indices[i] = self.indices[i]
+        done = False
+        for i in range(shapelen - 1, -1, -1):
+            if indices[i] < self.res_shape[i] - 1:
+                if i == self.dim:
+                    first_line = False
+                indices[i] += 1
+                offset += self.strides[i]
+                break
+            else:
+                if i == self.dim:
+                    first_line = True
+                indices[i] = 0
+                offset -= self.backstrides[i]
+        else:
+            done = True
+        res = instantiate(AxisIterator)
+        res.offset = offset
+        res.indices = indices
+        res.strides = self.strides
+        res.backstrides = self.backstrides
+        res.res_shape = self.res_shape
+        res._done = done
+        res.first_line = first_line
+        res.dim = self.dim
+        return res        
+
+    def done(self):
+        return self._done
+
 # ------ other iterators that are not part of the computation frame ----------
-
-class AxisIterator(object):
-    """ This object will return offsets of each start of the last stride
-    """
+    
+class SkipLastAxisIterator(object):
     def __init__(self, arr):
         self.arr = arr
         self.indices = [0] * (len(arr.shape) - 1)
@@ -125,4 +197,3 @@
                 self.offset -= self.arr.backstrides[i]
         else:
             self.done = True
-        
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
@@ -8,8 +8,8 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.rstring import StringBuilder
-from pypy.module.micronumpy.interp_iter import ArrayIterator,\
-     view_iter_from_arr, OneDimIterator, AxisIterator
+from pypy.module.micronumpy.interp_iter import ArrayIterator, OneDimIterator,\
+     SkipLastAxisIterator
 
 numpy_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
@@ -35,11 +35,12 @@
 slice_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
     virtualizables=['frame'],
-    reds=['self', 'frame', 'source', 'res_iter'],
+    reds=['self', 'frame', 'arr'],
     get_printable_location=signature.new_printable_location('slice'),
     name='numpy_slice',
 )
 
+
 def _find_shape_and_elems(space, w_iterable):
     shape = [space.len_w(w_iterable)]
     batch = space.listview(w_iterable)
@@ -156,9 +157,6 @@
 # (meaning that the realignment of elements crosses from one step into another)
 # return None so that the caller can raise an exception.
 def calc_new_strides(new_shape, old_shape, old_strides):
-    # Return the proper strides for new_shape, or None if the mapping crosses
-    # stepping boundaries
-
     # Assumes that prod(old_shape) == prod(new_shape), len(old_shape) > 1, and
     # len(new_shape) > 0
     steps = []
@@ -166,6 +164,7 @@
     oldI = 0
     new_strides = []
     if old_strides[0] < old_strides[-1]:
+        #Start at old_shape[0], old_stides[0]
         for i in range(len(old_shape)):
             steps.append(old_strides[i] / last_step)
             last_step *= old_shape[i]
@@ -183,10 +182,11 @@
             if n_new_elems_used == n_old_elems_to_use:
                 oldI += 1
                 if oldI >= len(old_shape):
-                    break
+                    continue
                 cur_step = steps[oldI]
                 n_old_elems_to_use *= old_shape[oldI]
     else:
+        #Start at old_shape[-1], old_strides[-1]
         for i in range(len(old_shape) - 1, -1, -1):
             steps.insert(0, old_strides[i] / last_step)
             last_step *= old_shape[i]
@@ -206,7 +206,7 @@
             if n_new_elems_used == n_old_elems_to_use:
                 oldI -= 1
                 if oldI < -len(old_shape):
-                    break
+                    continue
                 cur_step = steps[oldI]
                 n_old_elems_to_use *= old_shape[oldI]
     return new_strides
@@ -286,13 +286,17 @@
     descr_rpow = _binop_right_impl("power")
     descr_rmod = _binop_right_impl("mod")
 
-    def _reduce_ufunc_impl(ufunc_name):
-        def impl(self, space):
-            return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space, self, multidim=True)
+    def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
+        def impl(self, space, w_axis=None):
+            if space.is_w(w_axis, space.w_None):
+                w_axis = space.wrap(-1)
+            return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space,
+                                        self, True, promote_to_largest, w_axis)
         return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
 
     descr_sum = _reduce_ufunc_impl("add")
-    descr_prod = _reduce_ufunc_impl("multiply")
+    descr_sum_promote = _reduce_ufunc_impl("add", True)
+    descr_prod = _reduce_ufunc_impl("multiply", True)
     descr_max = _reduce_ufunc_impl("maximum")
     descr_min = _reduce_ufunc_impl("minimum")
 
@@ -377,7 +381,7 @@
         else:
             w_res = self.descr_mul(space, w_other)
             assert isinstance(w_res, BaseArray)
-            return w_res.descr_sum(space)
+            return w_res.descr_sum(space, space.wrap(-1))
 
     def get_concrete(self):
         raise NotImplementedError
@@ -565,21 +569,31 @@
             )
         return w_result
 
-    def descr_mean(self, space):
-        return space.div(self.descr_sum(space), space.wrap(self.size))
+    def descr_mean(self, space, w_axis=None):
+        if space.is_w(w_axis, space.w_None):
+            w_axis = space.wrap(-1)
+            w_denom = space.wrap(self.size)
+        else:
+            dim = space.int_w(w_axis)
+            w_denom = space.wrap(self.shape[dim])
+        return space.div(self.descr_sum_promote(space, w_axis), w_denom)
 
     def descr_var(self, space):
         # var = mean((values - mean(values)) ** 2)
-        w_res = self.descr_sub(space, self.descr_mean(space))
-        assert isinstance(w_res, BaseArray) 
+        w_res = self.descr_sub(space, self.descr_mean(space, space.w_None))
+        assert isinstance(w_res, BaseArray)
         w_res = w_res.descr_pow(space, space.wrap(2))
         assert isinstance(w_res, BaseArray)
-        return w_res.descr_mean(space)
+        return w_res.descr_mean(space, space.w_None)
 
     def descr_std(self, space):
         # std(v) = sqrt(var(v))
         return interp_ufuncs.get(space).sqrt.call(space, [self.descr_var(space)])
 
+    def descr_fill(self, space, w_value):
+        concr = self.get_concrete_or_scalar()
+        concr.fill(space, w_value)
+
     def descr_nonzero(self, space):
         if self.size > 1:
             raise OperationError(space.w_ValueError, space.wrap(
@@ -613,11 +627,12 @@
     def getitem(self, item):
         raise NotImplementedError
 
-    def find_sig(self, res_shape=None):
+    def find_sig(self, res_shape=None, arr=None):
         """ find a correct signature for the array
         """
         res_shape = res_shape or self.shape
-        return signature.find_sig(self.create_sig(res_shape), self)
+        arr = arr or self
+        return signature.find_sig(self.create_sig(), arr)
 
     def descr_array_iface(self, space):
         if not self.shape:
@@ -671,7 +686,10 @@
     def copy(self, space):
         return Scalar(self.dtype, self.value)
 
-    def create_sig(self, res_shape):
+    def fill(self, space, w_value):
+        self.value = self.dtype.coerce(space, w_value)
+
+    def create_sig(self):
         return signature.ScalarSignature(self.dtype)
 
     def get_concrete_or_scalar(self):
@@ -689,7 +707,8 @@
         self.name = name
 
     def _del_sources(self):
-        # Function for deleting references to source arrays, to allow garbage-collecting them
+        # Function for deleting references to source arrays,
+        # to allow garbage-collecting them
         raise NotImplementedError
 
     def compute(self):
@@ -741,11 +760,11 @@
         self.size = size
         VirtualArray.__init__(self, 'slice', shape, child.find_dtype())
 
-    def create_sig(self, res_shape):
+    def create_sig(self):
         if self.forced_result is not None:
-            return self.forced_result.create_sig(res_shape)
+            return self.forced_result.create_sig()
         return signature.VirtualSliceSignature(
-            self.child.create_sig(res_shape))
+            self.child.create_sig())
 
     def force_if_needed(self):
         if self.forced_result is None:
@@ -755,6 +774,7 @@
     def _del_sources(self):
         self.child = None
 
+
 class Call1(VirtualArray):
     def __init__(self, ufunc, name, shape, res_dtype, values):
         VirtualArray.__init__(self, name, shape, res_dtype)
@@ -765,16 +785,17 @@
     def _del_sources(self):
         self.values = None
 
-    def create_sig(self, res_shape):
+    def create_sig(self):
         if self.forced_result is not None:
-            return self.forced_result.create_sig(res_shape)
-        return signature.Call1(self.ufunc, self.name,
-                               self.values.create_sig(res_shape))
+            return self.forced_result.create_sig()
+        return signature.Call1(self.ufunc, self.name, self.values.create_sig())
 
 class Call2(VirtualArray):
     """
     Intermediate class for performing binary operations.
     """
+    _immutable_fields_ = ['left', 'right']
+
     def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right):
         VirtualArray.__init__(self, name, shape, res_dtype)
         self.ufunc = ufunc
@@ -789,12 +810,55 @@
         self.left = None
         self.right = None
 
-    def create_sig(self, res_shape):
+    def create_sig(self):
         if self.forced_result is not None:
-            return self.forced_result.create_sig(res_shape)
+            return self.forced_result.create_sig()
+        if self.shape != self.left.shape and self.shape != self.right.shape:
+            return signature.BroadcastBoth(self.ufunc, self.name,
+                                           self.calc_dtype,
+                                           self.left.create_sig(),
+                                           self.right.create_sig())
+        elif self.shape != self.left.shape:
+            return signature.BroadcastLeft(self.ufunc, self.name,
+                                           self.calc_dtype,
+                                           self.left.create_sig(),
+                                           self.right.create_sig())
+        elif self.shape != self.right.shape:
+            return signature.BroadcastRight(self.ufunc, self.name,
+                                            self.calc_dtype,
+                                            self.left.create_sig(),
+                                            self.right.create_sig())
         return signature.Call2(self.ufunc, self.name, self.calc_dtype,
-                               self.left.create_sig(res_shape),
-                               self.right.create_sig(res_shape))
+                               self.left.create_sig(), self.right.create_sig())
+
+class SliceArray(Call2):
+    def __init__(self, shape, dtype, left, right):
+        Call2.__init__(self, None, 'sliceloop', shape, dtype, dtype, left,
+                       right)
+
+    def create_sig(self):
+        lsig = self.left.create_sig()
+        rsig = self.right.create_sig()
+        if self.shape != self.right.shape:
+            return signature.SliceloopBroadcastSignature(self.ufunc,
+                                                         self.name,
+                                                         self.calc_dtype,
+                                                         lsig, rsig)
+        return signature.SliceloopSignature(self.ufunc, self.name,
+                                            self.calc_dtype,
+                                            lsig, rsig)
+
+class AxisReduce(Call2):
+    """ NOTE: this is only used as a container, you should never
+    encounter such things in the wild. Remove this comment
+    when we'll make AxisReduce lazy
+    """
+    _immutable_fields_ = ['left', 'right']
+
+    def __init__(self, ufunc, name, shape, dtype, left, right, dim):
+        Call2.__init__(self, ufunc, name, shape, dtype, dtype,
+                       left, right)
+        self.dim = dim
 
 class ConcreteArray(BaseArray):
     """ An array that have actual storage, whether owned or not
@@ -849,11 +913,6 @@
         self.strides = strides
         self.backstrides = backstrides
 
-    def array_sig(self, res_shape):
-        if res_shape is not None and self.shape != res_shape:
-            return signature.ViewSignature(self.dtype)
-        return signature.ArraySignature(self.dtype)
-
     def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
         '''Modifies builder with a representation of the array/slice
         The items will be seperated by a comma if comma is 1
@@ -867,14 +926,14 @@
         if size < 1:
             builder.append('[]')
             return
-        elif size == 1:
-            builder.append(dtype.itemtype.str_format(self.getitem(0)))
-            return
         if size > 1000:
             # Once this goes True it does not go back to False for recursive
             # calls
             use_ellipsis = True
         ndims = len(self.shape)
+        if ndims == 0:
+            builder.append(dtype.itemtype.str_format(self.getitem(0)))
+            return
         i = 0
         builder.append('[')
         if ndims > 1:
@@ -890,7 +949,7 @@
                     view.to_str(space, comma, builder, indent=indent + ' ',
                                                     use_ellipsis=use_ellipsis)
                 if i < self.shape[0] - 1:
-                    builder.append(ccomma +'\n' + indent + '...' + ncomma)
+                    builder.append(ccomma + '\n' + indent + '...' + ncomma)
                     i = self.shape[0] - 3
                 else:
                     i += 1
@@ -968,20 +1027,22 @@
             self.dtype is w_value.find_dtype()):
             self._fast_setslice(space, w_value)
         else:
-            self._sliceloop(w_value, res_shape)
+            arr = SliceArray(self.shape, self.dtype, self, w_value)
+            self._sliceloop(arr)
 
     def _fast_setslice(self, space, w_value):
         assert isinstance(w_value, ConcreteArray)
         itemsize = self.dtype.itemtype.get_element_size()
-        if len(self.shape) == 1:
+        shapelen = len(self.shape)
+        if shapelen == 1:
             rffi.c_memcpy(
                 rffi.ptradd(self.storage, self.start * itemsize),
                 rffi.ptradd(w_value.storage, w_value.start * itemsize),
                 self.size * itemsize
             )
         else:
-            dest = AxisIterator(self)
-            source = AxisIterator(w_value)
+            dest = SkipLastAxisIterator(self)
+            source = SkipLastAxisIterator(w_value)
             while not dest.done:
                 rffi.c_memcpy(
                     rffi.ptradd(self.storage, dest.offset * itemsize),
@@ -991,30 +1052,28 @@
                 source.next()
                 dest.next()
 
-    def _sliceloop(self, source, res_shape):
-        sig = source.find_sig(res_shape)
-        frame = sig.create_frame(source, res_shape)
-        res_iter = view_iter_from_arr(self)
-        shapelen = len(res_shape)
-        while not res_iter.done():
-            slice_driver.jit_merge_point(sig=sig,
-                                         frame=frame,
-                                         shapelen=shapelen,
-                                         self=self, source=source,
-                                         res_iter=res_iter)
-            self.setitem(res_iter.offset, sig.eval(frame, source).convert_to(
-                self.find_dtype()))
+    def _sliceloop(self, arr):
+        sig = arr.find_sig()
+        frame = sig.create_frame(arr)
+        shapelen = len(self.shape)
+        while not frame.done():
+            slice_driver.jit_merge_point(sig=sig, frame=frame, self=self,
+                                         arr=arr,
+                                         shapelen=shapelen)
+            sig.eval(frame, arr)
             frame.next(shapelen)
-            res_iter = res_iter.next(shapelen)
 
     def copy(self, space):
         array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
         array.setslice(space, self)
         return array
 
+    def fill(self, space, w_value):
+        self.setslice(space, scalar_w(space, self.dtype, w_value))
+
 
 class ViewArray(ConcreteArray):
-    def create_sig(self, res_shape):
+    def create_sig(self):
         return signature.ViewSignature(self.dtype)
 
 
@@ -1078,8 +1137,8 @@
         self.shape = new_shape
         self.calc_strides(new_shape)
 
-    def create_sig(self, res_shape):
-        return self.array_sig(res_shape)
+    def create_sig(self):
+        return signature.ArraySignature(self.dtype)
 
     def __del__(self):
         lltype.free(self.storage, flavor='raw', track_allocation=False)
@@ -1224,6 +1283,8 @@
     var = interp2app(BaseArray.descr_var),
     std = interp2app(BaseArray.descr_std),
 
+    fill = interp2app(BaseArray.descr_fill),
+
     copy = interp2app(BaseArray.descr_copy),
     reshape = interp2app(BaseArray.descr_reshape),
     tolist = interp2app(BaseArray.descr_tolist),
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
@@ -3,20 +3,29 @@
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
 from pypy.module.micronumpy import interp_boxes, interp_dtype
-from pypy.module.micronumpy.signature import ReduceSignature, ScalarSignature,\
-     find_sig, new_printable_location
+from pypy.module.micronumpy.signature import ReduceSignature,\
+     find_sig, new_printable_location, AxisReduceSignature, ScalarSignature
 from pypy.rlib import jit
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
 
 reduce_driver = jit.JitDriver(
-    greens = ['shapelen', "sig"],
-    virtualizables = ["frame"],
-    reds = ["frame", "self", "dtype", "value", "obj"],
+    greens=['shapelen', "sig"],
+    virtualizables=["frame"],
+    reds=["frame", "self", "dtype", "value", "obj"],
     get_printable_location=new_printable_location('reduce'),
     name='numpy_reduce',
 )
 
+axisreduce_driver = jit.JitDriver(
+    greens=['shapelen', 'sig'],
+    virtualizables=['frame'],
+    reds=['self','arr', 'identity', 'frame'],
+    name='numpy_axisreduce',
+    get_printable_location=new_printable_location('axisreduce'),
+)
+
+
 class W_Ufunc(Wrappable):
     _attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
     _immutable_fields_ = ["promote_to_float", "promote_bools", "name"]
@@ -49,18 +58,72 @@
             )
         return self.call(space, __args__.arguments_w)
 
-    def descr_reduce(self, space, w_obj):
-        return self.reduce(space, w_obj, multidim=False)
+    def descr_reduce(self, space, w_obj, w_dim=0):
+        """reduce(...)
+        reduce(a, axis=0)
 
-    def reduce(self, space, w_obj, multidim):
-        from pypy.module.micronumpy.interp_numarray import convert_to_array, Scalar
-        
+        Reduces `a`'s dimension by one, by applying ufunc along one axis.
+
+        Let :math:`a.shape = (N_0, ..., N_i, ..., N_{M-1})`.  Then
+        :math:`ufunc.reduce(a, axis=i)[k_0, ..,k_{i-1}, k_{i+1}, .., k_{M-1}]` =
+        the result of iterating `j` over :math:`range(N_i)`, cumulatively applying
+        ufunc to each :math:`a[k_0, ..,k_{i-1}, j, k_{i+1}, .., k_{M-1}]`.
+        For a one-dimensional array, reduce produces results equivalent to:
+        ::
+
+         r = op.identity # op = ufunc
+         for i in xrange(len(A)):
+           r = op(r, A[i])
+         return r
+
+        For example, add.reduce() is equivalent to sum().
+
+        Parameters
+        ----------
+        a : array_like
+            The array to act on.
+        axis : int, optional
+            The axis along which to apply the reduction.
+
+        Examples
+        --------
+        >>> np.multiply.reduce([2,3,5])
+        30
+
+        A multi-dimensional array example:
+
+        >>> X = np.arange(8).reshape((2,2,2))
+        >>> X
+        array([[[0, 1],
+                [2, 3]],
+               [[4, 5],
+                [6, 7]]])
+        >>> np.add.reduce(X, 0)
+        array([[ 4,  6],
+               [ 8, 10]])
+        >>> np.add.reduce(X) # confirm: default axis value is 0
+        array([[ 4,  6],
+               [ 8, 10]])
+        >>> np.add.reduce(X, 1)
+        array([[ 2,  4],
+               [10, 12]])
+        >>> np.add.reduce(X, 2)
+        array([[ 1,  5],
+               [ 9, 13]])
+        """
+        return self.reduce(space, w_obj, False, False, w_dim)
+
+    def reduce(self, space, w_obj, multidim, promote_to_largest, w_dim):
+        from pypy.module.micronumpy.interp_numarray import convert_to_array, \
+                                                           Scalar
         if self.argcount != 2:
             raise OperationError(space.w_ValueError, space.wrap("reduce only "
                 "supported for binary functions"))
-
+        dim = space.int_w(w_dim)
         assert isinstance(self, W_Ufunc2)
         obj = convert_to_array(space, w_obj)
+        if dim >= len(obj.shape):
+            raise OperationError(space.w_ValueError, space.wrap("axis(=%d) out of bounds" % dim))
         if isinstance(obj, Scalar):
             raise OperationError(space.w_TypeError, space.wrap("cannot reduce "
                 "on a scalar"))
@@ -68,26 +131,80 @@
         size = obj.size
         dtype = find_unaryop_result_dtype(
             space, obj.find_dtype(),
-            promote_to_largest=True
+            promote_to_float=self.promote_to_float,
+            promote_to_largest=promote_to_largest,
+            promote_bools=True
         )
         shapelen = len(obj.shape)
+        if self.identity is None and size == 0:
+            raise operationerrfmt(space.w_ValueError, "zero-size array to "
+                    "%s.reduce without identity", self.name)
+        if shapelen > 1 and dim >= 0:
+            res = self.do_axis_reduce(obj, dtype, dim)
+            return space.wrap(res)
+        scalarsig = ScalarSignature(dtype)
         sig = find_sig(ReduceSignature(self.func, self.name, dtype,
-                                       ScalarSignature(dtype),
-                                       obj.create_sig(obj.shape)), obj)
+                                       scalarsig,
+                                       obj.create_sig()), obj)
         frame = sig.create_frame(obj)
-        if shapelen > 1 and not multidim:
-            raise OperationError(space.w_NotImplementedError,
-                space.wrap("not implemented yet"))
         if self.identity is None:
-            if size == 0:
-                raise operationerrfmt(space.w_ValueError, "zero-size array to "
-                    "%s.reduce without identity", self.name)
             value = sig.eval(frame, obj).convert_to(dtype)
             frame.next(shapelen)
         else:
             value = self.identity.convert_to(dtype)
         return self.reduce_loop(shapelen, sig, frame, value, obj, dtype)
 
+    def do_axis_reduce(self, obj, dtype, dim):
+        from pypy.module.micronumpy.interp_numarray import AxisReduce,\
+             W_NDimArray
+        
+        shape = obj.shape[0:dim] + obj.shape[dim + 1:len(obj.shape)]
+        size = 1
+        for s in shape:
+            size *= s
+        result = W_NDimArray(size, shape, dtype)
+        rightsig = obj.create_sig()
+        # note - this is just a wrapper so signature can fetch
+        #        both left and right, nothing more, especially
+        #        this is not a true virtual array, because shapes
+        #        don't quite match
+        arr = AxisReduce(self.func, self.name, obj.shape, dtype,
+                         result, obj, dim)
+        scalarsig = ScalarSignature(dtype)
+        sig = find_sig(AxisReduceSignature(self.func, self.name, dtype,
+                                           scalarsig, rightsig), arr)
+        assert isinstance(sig, AxisReduceSignature)
+        frame = sig.create_frame(arr)
+        shapelen = len(obj.shape)
+        if self.identity is not None:
+            identity = self.identity.convert_to(dtype)
+        else:
+            identity = None
+        self.reduce_axis_loop(frame, sig, shapelen, arr, identity)
+        return result
+
+    def reduce_axis_loop(self, frame, sig, shapelen, arr, identity):
+        # note - we can be advanterous here, depending on the exact field
+        # layout. For now let's say we iterate the original way and
+        # simply follow the original iteration order
+        while not frame.done():
+            axisreduce_driver.jit_merge_point(frame=frame, self=self,
+                                              sig=sig,
+                                              identity=identity,
+                                              shapelen=shapelen, arr=arr)
+            iter = frame.get_final_iter()
+            v = sig.eval(frame, arr).convert_to(sig.calc_dtype)
+            if iter.first_line:
+                if identity is not None:
+                    value = self.func(sig.calc_dtype, identity, v)
+                else:
+                    value = v
+            else:
+                cur = arr.left.getitem(iter.offset)
+                value = self.func(sig.calc_dtype, cur, v)
+            arr.left.setitem(iter.offset, value)
+            frame.next(shapelen)
+
     def reduce_loop(self, shapelen, sig, frame, value, obj, dtype):
         while not frame.done():
             reduce_driver.jit_merge_point(sig=sig,
@@ -95,10 +212,12 @@
                                           value=value, obj=obj, frame=frame,
                                           dtype=dtype)
             assert isinstance(sig, ReduceSignature)
-            value = sig.binfunc(dtype, value, sig.eval(frame, obj).convert_to(dtype))
+            value = sig.binfunc(dtype, value,
+                                sig.eval(frame, obj).convert_to(dtype))
             frame.next(shapelen)
         return value
 
+
 class W_Ufunc1(W_Ufunc):
     argcount = 1
 
@@ -183,6 +302,7 @@
     reduce = interp2app(W_Ufunc.descr_reduce),
 )
 
+
 def find_binop_result_dtype(space, dt1, dt2, promote_to_float=False,
     promote_bools=False):
     # dt1.num should be <= dt2.num
@@ -231,6 +351,7 @@
             dtypenum += 3
         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):
@@ -255,6 +376,7 @@
             assert False
     return dt
 
+
 def find_dtype_for_scalar(space, w_obj, current_guess=None):
     bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
     long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
@@ -327,6 +449,7 @@
 
             ("fabs", "fabs", 1, {"promote_to_float": True}),
             ("floor", "floor", 1, {"promote_to_float": True}),
+            ("ceil", "ceil", 1, {"promote_to_float": True}),
             ("exp", "exp", 1, {"promote_to_float": True}),
 
             ('sqrt', 'sqrt', 1, {'promote_to_float': True}),
@@ -348,7 +471,8 @@
 
         identity = extra_kwargs.get("identity")
         if identity is not None:
-            identity = interp_dtype.get_dtype_cache(space).w_longdtype.box(identity)
+            identity = \
+                 interp_dtype.get_dtype_cache(space).w_longdtype.box(identity)
         extra_kwargs["identity"] = identity
 
         func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -1,10 +1,32 @@
 from pypy.rlib.objectmodel import r_dict, compute_identity_hash, compute_hash
 from pypy.rlib.rarithmetic import intmask
 from pypy.module.micronumpy.interp_iter import ViewIterator, ArrayIterator, \
-     OneDimIterator, ConstantIterator
-from pypy.module.micronumpy.strides import calculate_slice_strides
+     ConstantIterator, AxisIterator, ViewTransform,\
+     BroadcastTransform
 from pypy.rlib.jit import hint, unroll_safe, promote
 
+""" Signature specifies both the numpy expression that has been constructed
+and the assembler to be compiled. This is a very important observation -
+Two expressions will be using the same assembler if and only if they are
+compiled to the same signature.
+
+This is also a very convinient tool for specializations. For example
+a + a and a + b (where a != b) will compile to different assembler because
+we specialize on the same array access.
+
+When evaluating, signatures will create iterators per signature node,
+potentially sharing some of them. Iterators depend also on the actual
+expression, they're not only dependant on the array itself. For example
+a + b where a is dim 2 and b is dim 1 would create a broadcasted iterator for
+the array b.
+
+Such iterator changes are called Transformations. An actual iterator would
+be a combination of array and various transformation, like view, broadcast,
+dimension swapping etc.
+
+See interp_iter for transformations
+"""
+
 def new_printable_location(driver_name):
     def get_printable_location(shapelen, sig):
         return 'numpy ' + sig.debug_repr() + ' [%d dims,%s]' % (shapelen, driver_name)
@@ -33,7 +55,8 @@
         return sig
 
 class NumpyEvalFrame(object):
-    _virtualizable2_ = ['iterators[*]', 'final_iter', 'arraylist[*]']
+    _virtualizable2_ = ['iterators[*]', 'final_iter', 'arraylist[*]',
+                        'value', 'identity']
 
     @unroll_safe
     def __init__(self, iterators, arrays):
@@ -51,7 +74,7 @@
     def done(self):
         final_iter = promote(self.final_iter)
         if final_iter < 0:
-            return False
+            assert False
         return self.iterators[final_iter].done()
 
     @unroll_safe
@@ -59,6 +82,12 @@
         for i in range(len(self.iterators)):
             self.iterators[i] = self.iterators[i].next(shapelen)
 
+    def get_final_iter(self):
+        final_iter = promote(self.final_iter)
+        if final_iter < 0:
+            assert False
+        return self.iterators[final_iter]
+
 def _add_ptr_to_cache(ptr, cache):
     i = 0
     for p in cache:
@@ -70,6 +99,9 @@
         cache.append(ptr)
         return res
 
+def new_cache():
+    return r_dict(sigeq_no_numbering, sighash)
+
 class Signature(object):
     _attrs_ = ['iter_no', 'array_no']
     _immutable_fields_ = ['iter_no', 'array_no']
@@ -78,7 +110,7 @@
     iter_no = 0
 
     def invent_numbering(self):
-        cache = r_dict(sigeq_no_numbering, sighash)
+        cache = new_cache()
         allnumbers = []
         self._invent_numbering(cache, allnumbers)
 
@@ -95,13 +127,13 @@
             allnumbers.append(no)
         self.iter_no = no
 
-    def create_frame(self, arr, res_shape=None):
-        res_shape = res_shape or arr.shape
+    def create_frame(self, arr):
         iterlist = []
         arraylist = []
-        self._create_iter(iterlist, arraylist, arr, res_shape, [])
+        self._create_iter(iterlist, arraylist, arr, [])
         return NumpyEvalFrame(iterlist, arraylist)
 
+
 class ConcreteSignature(Signature):
     _immutable_fields_ = ['dtype']
 
@@ -120,16 +152,6 @@
     def hash(self):
         return compute_identity_hash(self.dtype)
 
-    def allocate_view_iter(self, arr, res_shape, chunklist):
-        r = arr.shape, arr.start, arr.strides, arr.backstrides
-        if chunklist:
-            for chunkelem in chunklist:
-                r = calculate_slice_strides(r[0], r[1], r[2], r[3], chunkelem)
-        shape, start, strides, backstrides = r
-        if len(res_shape) == 1:
-            return OneDimIterator(start, strides[0], res_shape[0])
-        return ViewIterator(start, strides, backstrides, shape, res_shape)
-
 class ArraySignature(ConcreteSignature):
     def debug_repr(self):
         return 'Array'
@@ -141,22 +163,21 @@
         # is not of a concrete class it means that we have a _forced_result,
         # otherwise the signature would not match
         assert isinstance(concr, ConcreteArray)
+        assert concr.dtype is self.dtype
         self.array_no = _add_ptr_to_cache(concr.storage, cache)
 
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
         from pypy.module.micronumpy.interp_numarray import ConcreteArray
         concr = arr.get_concrete()
         assert isinstance(concr, ConcreteArray)
         storage = concr.storage
         if self.iter_no >= len(iterlist):
-            iterlist.append(self.allocate_iter(concr, res_shape, chunklist))
+            iterlist.append(self.allocate_iter(concr, transforms))
         if self.array_no >= len(arraylist):
             arraylist.append(storage)
 
-    def allocate_iter(self, arr, res_shape, chunklist):
-        if chunklist:
-            return self.allocate_view_iter(arr, res_shape, chunklist)
-        return ArrayIterator(arr.size)
+    def allocate_iter(self, arr, transforms):
+        return ArrayIterator(arr.size).apply_transformations(arr, transforms)
 
     def eval(self, frame, arr):
         iter = frame.iterators[self.iter_no]
@@ -169,7 +190,7 @@
     def _invent_array_numbering(self, arr, cache):
         pass
 
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
         if self.iter_no >= len(iterlist):
             iter = ConstantIterator()
             iterlist.append(iter)
@@ -189,8 +210,9 @@
         allnumbers.append(no)
         self.iter_no = no
 
-    def allocate_iter(self, arr, res_shape, chunklist):
-        return self.allocate_view_iter(arr, res_shape, chunklist)
+    def allocate_iter(self, arr, transforms):
+        return ViewIterator(arr.start, arr.strides, arr.backstrides,
+                            arr.shape).apply_transformations(arr, transforms)
 
 class VirtualSliceSignature(Signature):
     def __init__(self, child):
@@ -201,6 +223,9 @@
         assert isinstance(arr, VirtualSlice)
         self.child._invent_array_numbering(arr.child, cache)
 
+    def _invent_numbering(self, cache, allnumbers):
+        self.child._invent_numbering(new_cache(), allnumbers)
+
     def hash(self):
         return intmask(self.child.hash() ^ 1234)
 
@@ -210,12 +235,11 @@
         assert isinstance(other, VirtualSliceSignature)
         return self.child.eq(other.child, compare_array_no)
 
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
         from pypy.module.micronumpy.interp_numarray import VirtualSlice
         assert isinstance(arr, VirtualSlice)
-        chunklist.append(arr.chunks)
-        self.child._create_iter(iterlist, arraylist, arr.child, res_shape,
-                                chunklist)
+        transforms = transforms + [ViewTransform(arr.chunks)]
+        self.child._create_iter(iterlist, arraylist, arr.child, transforms)
 
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import VirtualSlice
@@ -251,11 +275,10 @@
         assert isinstance(arr, Call1)
         self.child._invent_array_numbering(arr.values, cache)
 
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
         from pypy.module.micronumpy.interp_numarray import Call1
         assert isinstance(arr, Call1)
-        self.child._create_iter(iterlist, arraylist, arr.values, res_shape,
-                                chunklist)
+        self.child._create_iter(iterlist, arraylist, arr.values, transforms)
 
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import Call1
@@ -296,29 +319,68 @@
         self.left._invent_numbering(cache, allnumbers)
         self.right._invent_numbering(cache, allnumbers)
 
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
         from pypy.module.micronumpy.interp_numarray import Call2
 
         assert isinstance(arr, Call2)
-        self.left._create_iter(iterlist, arraylist, arr.left, res_shape,
-                               chunklist)
-        self.right._create_iter(iterlist, arraylist, arr.right, res_shape,
-                                chunklist)
+        self.left._create_iter(iterlist, arraylist, arr.left, transforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, transforms)
 
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import Call2
         assert isinstance(arr, Call2)
         lhs = self.left.eval(frame, arr.left).convert_to(self.calc_dtype)
         rhs = self.right.eval(frame, arr.right).convert_to(self.calc_dtype)
+        
         return self.binfunc(self.calc_dtype, lhs, rhs)
 
     def debug_repr(self):
         return 'Call2(%s, %s, %s)' % (self.name, self.left.debug_repr(),
                                       self.right.debug_repr())
 
+class BroadcastLeft(Call2):
+    def _invent_numbering(self, cache, allnumbers):
+        self.left._invent_numbering(new_cache(), allnumbers)
+        self.right._invent_numbering(cache, allnumbers)
+    
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import Call2
+
+        assert isinstance(arr, Call2)
+        ltransforms = transforms + [BroadcastTransform(arr.shape)]
+        self.left._create_iter(iterlist, arraylist, arr.left, ltransforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, transforms)
+
+class BroadcastRight(Call2):
+    def _invent_numbering(self, cache, allnumbers):
+        self.left._invent_numbering(cache, allnumbers)
+        self.right._invent_numbering(new_cache(), allnumbers)
+
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import Call2
+
+        assert isinstance(arr, Call2)
+        rtransforms = transforms + [BroadcastTransform(arr.shape)]
+        self.left._create_iter(iterlist, arraylist, arr.left, transforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
+
+class BroadcastBoth(Call2):
+    def _invent_numbering(self, cache, allnumbers):
+        self.left._invent_numbering(new_cache(), allnumbers)
+        self.right._invent_numbering(new_cache(), allnumbers)
+
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import Call2
+
+        assert isinstance(arr, Call2)
+        rtransforms = transforms + [BroadcastTransform(arr.shape)]
+        ltransforms = transforms + [BroadcastTransform(arr.shape)]
+        self.left._create_iter(iterlist, arraylist, arr.left, ltransforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
+
 class ReduceSignature(Call2):
-    def _create_iter(self, iterlist, arraylist, arr, res_shape, chunklist):
-        self.right._create_iter(iterlist, arraylist, arr, res_shape, chunklist)
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        self.right._create_iter(iterlist, arraylist, arr, transforms)
 
     def _invent_numbering(self, cache, allnumbers):
         self.right._invent_numbering(cache, allnumbers)
@@ -328,3 +390,63 @@
 
     def eval(self, frame, arr):
         return self.right.eval(frame, arr)
+
+    def debug_repr(self):
+        return 'ReduceSig(%s, %s)' % (self.name, self.right.debug_repr())
+
+class SliceloopSignature(Call2):
+    def eval(self, frame, arr):
+        from pypy.module.micronumpy.interp_numarray import Call2
+        
+        assert isinstance(arr, Call2)
+        ofs = frame.iterators[0].offset
+        arr.left.setitem(ofs, self.right.eval(frame, arr.right).convert_to(
+            self.calc_dtype))
+    
+    def debug_repr(self):
+        return 'SliceLoop(%s, %s, %s)' % (self.name, self.left.debug_repr(),
+                                          self.right.debug_repr())
+
+class SliceloopBroadcastSignature(SliceloopSignature):
+    def _invent_numbering(self, cache, allnumbers):
+        self.left._invent_numbering(new_cache(), allnumbers)
+        self.right._invent_numbering(cache, allnumbers)
+
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import SliceArray
+
+        assert isinstance(arr, SliceArray)
+        rtransforms = transforms + [BroadcastTransform(arr.shape)]
+        self.left._create_iter(iterlist, arraylist, arr.left, transforms)
+        self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
+
+class AxisReduceSignature(Call2):
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import AxisReduce,\
+             ConcreteArray
+
+        assert isinstance(arr, AxisReduce)
+        left = arr.left
+        assert isinstance(left, ConcreteArray)
+        iterlist.append(AxisIterator(left.start, arr.dim, arr.shape,
+                                     left.strides, left.backstrides))
+        self.right._create_iter(iterlist, arraylist, arr.right, transforms)
+
+    def _invent_numbering(self, cache, allnumbers):
+        allnumbers.append(0)
+        self.right._invent_numbering(cache, allnumbers)
+
+    def _invent_array_numbering(self, arr, cache):
+        from pypy.module.micronumpy.interp_numarray import AxisReduce
+
+        assert isinstance(arr, AxisReduce)
+        self.right._invent_array_numbering(arr.right, cache)
+
+    def eval(self, frame, arr):
+        from pypy.module.micronumpy.interp_numarray import AxisReduce
+
+        assert isinstance(arr, AxisReduce)
+        return self.right.eval(frame, arr.right).convert_to(self.calc_dtype)
+    
+    def debug_repr(self):
+        return 'AxisReduceSig(%s, %s)' % (self.name, self.right.debug_repr())
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
@@ -166,14 +166,11 @@
         # You can't subclass dtype
         raises(TypeError, type, "Foo", (dtype,), {})
 
-    def test_new(self):
-        import _numpypy as np
-        assert np.int_(4) == 4
-        assert np.float_(3.4) == 3.4
+    def test_aliases(self):
+        from _numpypy import dtype
 
-    def test_pow(self):
-        from _numpypy import int_
-        assert int_(4) ** 2 == 16
+        assert dtype("float") is dtype(float)
+
 
 class AppTestTypes(BaseNumpyAppTest):
     def test_abstract_types(self):
@@ -189,6 +186,15 @@
         raises(TypeError, numpy.floating, 0)
         raises(TypeError, numpy.inexact, 0)
 
+    def test_new(self):
+        import _numpypy as np
+        assert np.int_(4) == 4
+        assert np.float_(3.4) == 3.4
+
+    def test_pow(self):
+        from _numpypy import int_
+        assert int_(4) ** 2 == 16
+
     def test_bool(self):
         import _numpypy as numpy
 
@@ -318,7 +324,7 @@
         else:
             raises(OverflowError, numpy.int64, 9223372036854775807)
             raises(OverflowError, numpy.int64, '9223372036854775807')
-        
+
         raises(OverflowError, numpy.int64, 9223372036854775808)
         raises(OverflowError, numpy.int64, '9223372036854775808')
 
diff --git a/pypy/module/micronumpy/test/test_module.py b/pypy/module/micronumpy/test/test_module.py
--- a/pypy/module/micronumpy/test/test_module.py
+++ b/pypy/module/micronumpy/test/test_module.py
@@ -2,16 +2,11 @@
 
 
 class AppTestNumPyModule(BaseNumpyAppTest):
-    def test_mean(self):
-        from _numpypy import array, mean
-        assert mean(array(range(5))) == 2.0
-        assert mean(range(5)) == 2.0
-
     def test_average(self):
         from _numpypy import array, average
         assert average(range(10)) == 4.5
         assert average(array(range(10))) == 4.5
-        
+
     def test_sum(self):
         from _numpypy import array, sum
         assert sum(range(10)) == 45
@@ -21,7 +16,7 @@
         from _numpypy import array, min
         assert min(range(10)) == 0
         assert min(array(range(10))) == 0
-        
+
     def test_max(self):
         from _numpypy import array, max
         assert max(range(10)) == 9
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
@@ -157,6 +157,8 @@
         assert calc_new_strides([2, 3, 4], [8, 3], [1, 16]) is None
         assert calc_new_strides([24], [2, 4, 3], [48, 6, 1]) is None
         assert calc_new_strides([24], [2, 4, 3], [24, 6, 2]) == [2]
+        assert calc_new_strides([105, 1], [3, 5, 7], [35, 7, 1]) == [1, 1]
+        assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1]) == [105, 1]
 
 
 class AppTestNumArray(BaseNumpyAppTest):
@@ -246,6 +248,10 @@
         c = b.copy()
         assert (c == b).all()
 
+        a = arange(15).reshape(5,3)
+        b = a.copy()
+        assert (b == a).all()
+
     def test_iterator_init(self):
         from _numpypy import array
         a = array(range(5))
@@ -724,6 +730,12 @@
         a = array(range(5))
         assert a.mean() == 2.0
         assert a[:4].mean() == 1.5
+        a = array(range(105)).reshape(3, 5, 7)
+        b = a.mean(axis=0)
+        b[0, 0]==35.
+        assert a.mean(axis=0)[0, 0] == 35
+        assert (b == array(range(35, 70), dtype=float).reshape(5, 7)).all()
+        assert (a.mean(2) == array(range(0, 15), dtype=float).reshape(3, 5) * 7 + 3).all()
 
     def test_sum(self):
         from _numpypy import array
@@ -734,6 +746,34 @@
         a = array([True] * 5, bool)
         assert a.sum() == 5
 
+        raises(TypeError, 'a.sum(2, 3)')
+
+    def test_reduce_nd(self):
+        from numpypy import arange, array, multiply
+        a = arange(15).reshape(5, 3)
+        assert a.sum() == 105
+        assert a.max() == 14
+        assert array([]).sum() == 0.0
+        raises(ValueError, 'array([]).max()')
+        assert (a.sum(0) == [30, 35, 40]).all()
+        assert (a.sum(axis=0) == [30, 35, 40]).all()
+        assert (a.sum(1) == [3, 12, 21, 30, 39]).all()
+        assert (a.max(0) == [12, 13, 14]).all()
+        assert (a.max(1) == [2, 5, 8, 11, 14]).all()
+        assert ((a + a).max() == 28)
+        assert ((a + a).max(0) == [24, 26, 28]).all()
+        assert ((a + a).sum(1) == [6, 24, 42, 60, 78]).all()
+        assert (multiply.reduce(a) == array([0, 3640, 12320])).all()
+        a = array(range(105)).reshape(3, 5, 7)
+        assert (a[:, 1, :].sum(0) == [126, 129, 132, 135, 138, 141, 144]).all()
+        assert (a[:, 1, :].sum(1) == [70, 315, 560]).all()
+        raises (ValueError, 'a[:, 1, :].sum(2)')
+        assert ((a + a).T.sum(2).T == (a + a).sum(0)).all()
+        assert (a.reshape(1,-1).sum(0) == range(105)).all()
+        assert (a.reshape(1,-1).sum(1) == 5460)
+        assert (array([[1,2],[3,4]]).prod(0) == [3, 8]).all()
+        assert (array([[1,2],[3,4]]).prod(1) == [2, 12]).all()
+
     def test_identity(self):
         from _numpypy import identity, array
         from _numpypy import int32, float64, dtype
@@ -1262,6 +1302,28 @@
         assert isinstance(i['data'][0], int)
         raises(TypeError, getattr, array(3), '__array_interface__')
 
+    def test_fill(self):
+        from _numpypy import array
+
+        a = array([1, 2, 3])
+        a.fill(10)
+        assert (a == [10, 10, 10]).all()
+        a.fill(False)
+        assert (a == [0, 0, 0]).all()
+
+        b = a[:1]
+        b.fill(4)
+        assert (b == [4]).all()
+        assert (a == [4, 0, 0]).all()
+
+        c = b + b
+        c.fill(27)
+        assert (c == [27]).all()
+
+        d = array(10)
+        d.fill(100)
+        assert d == 100
+
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
@@ -1401,9 +1463,11 @@
         assert repr(a) == "array(0.0)"
         a = array(0.2)
         assert repr(a) == "array(0.2)"
+        a = array([2])
+        assert repr(a) == "array([2])"
 
     def test_repr_multi(self):
-        from _numpypy import arange, zeros
+        from _numpypy import arange, zeros, array
         a = zeros((3, 4))
         assert repr(a) == '''array([[0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0],
@@ -1426,6 +1490,9 @@
        [498, 999],
        [499, 1000],
        [500, 1001]])'''
+        a = arange(2).reshape((2,1))
+        assert repr(a) == '''array([[0],
+       [1]])'''
 
     def test_repr_slice(self):
         from _numpypy import array, zeros
@@ -1510,14 +1577,3 @@
         a = arange(0, 0.8, 0.1)
         assert len(a) == 8
         assert arange(False, True, True).dtype is dtype(int)
-
-
-class AppTestRanges(BaseNumpyAppTest):
-    def test_app_reshape(self):
-        from _numpypy import arange, array, dtype, reshape
-        a = arange(12)
-        b = reshape(a, (3, 4))
-        assert b.shape == (3, 4)
-        a = range(12)
-        b = reshape(a, (3, 4))
-        assert b.shape == (3, 4)
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
@@ -190,14 +190,24 @@
         for i in range(3):
             assert c[i] == a[i] - b[i]
 
-    def test_floor(self):
-        from _numpypy import array, floor
-
-        reference = [-2.0, -1.0, 0.0, 1.0, 1.0]
-        a = array([-1.4, -1.0, 0.0, 1.0, 1.4])
+    def test_floorceil(self):
+        from _numpypy import array, floor, ceil
+        import math
+        reference = [-2.0, -2.0, -1.0, 0.0, 1.0, 1.0, 0]
+        a = array([-1.4, -1.5, -1.0, 0.0, 1.0, 1.4, 0.5])
         b = floor(a)
         for i in range(5):
             assert b[i] == reference[i]
+        reference = [-1.0, -1.0, -1.0, 0.0, 1.0, 2.0, 1.0]
+        a = array([-1.4, -1.5, -1.0, 0.0, 1.0, 1.4, 0.5])
+        b = ceil(a)
+        assert (reference == b).all()
+        inf = float("inf")
+        data = [1.5, 2.9999, -1.999, inf]
+        results = [math.floor(x) for x in data]
+        assert (floor(data) == results).all()
+        results = [math.ceil(x) for x in data]
+        assert (ceil(data) == results).all()
 
     def test_copysign(self):
         from _numpypy import array, copysign
@@ -238,7 +248,7 @@
             assert b[i] == math.sin(a[i])
 
         a = sin(array([True, False], dtype=bool))
-        assert abs(a[0] - sin(1)) < 1e-7 # a[0] will be less precise
+        assert abs(a[0] - sin(1)) < 1e-7  # a[0] will be less precise
         assert a[1] == 0.0
 
     def test_cos(self):
@@ -259,7 +269,6 @@
         for i in range(len(a)):
             assert b[i] == math.tan(a[i])
 
-
     def test_arcsin(self):
         import math
         from _numpypy import array, arcsin
@@ -283,7 +292,6 @@
         for i in range(len(a)):
             assert b[i] == math.acos(a[i])
 
-
         a = array([-10, -1.5, -1.01, 1.01, 1.5, 10, float('nan'), float('inf'), float('-inf')])
         b = arccos(a)
         for f in b:
@@ -298,7 +306,7 @@
         for i in range(len(a)):
             assert b[i] == math.atan(a[i])
 
-        a  = array([float('nan')])
+        a = array([float('nan')])
         b = arctan(a)
         assert math.isnan(b[0])
 
@@ -336,9 +344,9 @@
         from _numpypy import sin, add
 
         raises(ValueError, sin.reduce, [1, 2, 3])
-        raises(TypeError, add.reduce, 1)
+        raises(ValueError, add.reduce, 1)
 
-    def test_reduce(self):
+    def test_reduce_1d(self):
         from _numpypy import add, maximum
 
         assert add.reduce([1, 2, 3]) == 6
@@ -346,6 +354,12 @@
         assert maximum.reduce([1, 2, 3]) == 3
         raises(ValueError, maximum.reduce, [])
 
+    def test_reduceND(self):
+        from numpypy import add, arange
+        a = arange(12).reshape(3, 4)
+        assert (add.reduce(a, 0) == [12, 15, 18, 21]).all()
+        assert (add.reduce(a, 1) == [6.0, 22.0, 38.0]).all()
+
     def test_comparisons(self):
         import operator
         from _numpypy import equal, not_equal, less, less_equal, greater, greater_equal
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
@@ -47,6 +47,8 @@
         def f(i):
             interp = InterpreterState(codes[i])
             interp.run(space)
+            if not len(interp.results):
+                raise Exception("need results")
             w_res = interp.results[-1]
             if isinstance(w_res, BaseArray):
                 concr = w_res.get_concrete_or_scalar()
@@ -115,6 +117,28 @@
                                 "int_add": 1, "int_ge": 1, "guard_false": 1,
                                 "jump": 1, 'arraylen_gc': 1})
 
+    def define_axissum():
+        return """
+        a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
+        b = sum(a,0)
+        b -> 1
+        """
+
+    def test_axissum(self):
+        result = self.run("axissum")
+        assert result == 30
+        # XXX note - the bridge here is fairly crucial and yet it's pretty
+        #            bogus. We need to improve the situation somehow.
+        self.check_simple_loop({'getinteriorfield_raw': 2,
+                                'setinteriorfield_raw': 1,
+                                'arraylen_gc': 1,
+                                'guard_true': 1,
+                                'int_lt': 1,
+                                'jump': 1,
+                                'float_add': 1,
+                                'int_add': 3,
+                                })
+
     def define_prod():
         return """
         a = |30|
@@ -193,9 +217,9 @@
         # This is the sum of the ops for both loops, however if you remove the
         # optimization then you end up with 2 float_adds, so we can still be
         # sure it was optimized correctly.
-        self.check_resops({'setinteriorfield_raw': 4, 'getfield_gc': 26,
+        self.check_resops({'setinteriorfield_raw': 4, 'getfield_gc': 22,
                            'getarrayitem_gc': 4, 'getarrayitem_gc_pure': 2,
-                           'getfield_gc_pure': 4,
+                           'getfield_gc_pure': 8,
                            'guard_class': 8, 'int_add': 8, 'float_mul': 2,
                            'jump': 2, 'int_ge': 4,
                            'getinteriorfield_raw': 4, 'float_add': 2,
@@ -212,7 +236,8 @@
     def test_ufunc(self):
         result = self.run("ufunc")
         assert result == -6
-        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1, "float_neg": 1,
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_neg": 1,
                                 "setinteriorfield_raw": 1, "int_add": 2,
                                 "int_ge": 1, "guard_false": 1, "jump": 1,
                                 'arraylen_gc': 1})
@@ -322,10 +347,10 @@
         result = self.run("setslice")
         assert result == 11.0
         self.check_trace_count(1)
-        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
-                                'setinteriorfield_raw': 1, 'int_add': 3,
-                                'int_lt': 1, 'guard_true': 1, 'jump': 1,
-                                'arraylen_gc': 3})
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 2,
+                                'int_eq': 1, 'guard_false': 1, 'jump': 1,
+                                'arraylen_gc': 1})
 
     def define_virtual_slice():
         return """
@@ -339,11 +364,12 @@
         result = self.run("virtual_slice")
         assert result == 4
         self.check_trace_count(1)
-        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
                                 'setinteriorfield_raw': 1, 'int_add': 2,
                                 'int_ge': 1, 'guard_false': 1, 'jump': 1,
                                 'arraylen_gc': 1})
 
+
 class TestNumpyOld(LLJitMixin):
     def setup_class(cls):
         py.test.skip("old")
@@ -377,4 +403,3 @@
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
         assert result == f(5)
-
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -374,6 +374,10 @@
         return math.floor(v)
 
     @simple_unary_op
+    def ceil(self, v):
+        return math.ceil(v)
+
+    @simple_unary_op
     def exp(self, v):
         try:
             return math.exp(v)
@@ -436,4 +440,4 @@
 class Float64(BaseType, Float):
     T = rffi.DOUBLE
     BoxType = interp_boxes.W_Float64Box
-    format_code = "d"
\ No newline at end of file
+    format_code = "d"
diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py
--- a/pypy/module/pypyjit/__init__.py
+++ b/pypy/module/pypyjit/__init__.py
@@ -11,6 +11,7 @@
         'set_optimize_hook': 'interp_resop.set_optimize_hook',
         'set_abort_hook': 'interp_resop.set_abort_hook',
         'ResOperation': 'interp_resop.WrappedOp',
+        'DebugMergePoint': 'interp_resop.DebugMergePoint',
         'Box': 'interp_resop.WrappedBox',
     }
 
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -1,5 +1,6 @@
 
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
+     interp_attrproperty, interp_attrproperty_w)
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.gateway import unwrap_spec, interp2app, NoneNotWrapped
 from pypy.interpreter.pycode import PyCode
@@ -10,6 +11,7 @@
 from pypy.jit.metainterp.resoperation import rop, AbstractResOp
 from pypy.rlib.nonconst import NonConstant
 from pypy.rlib import jit_hooks
+from pypy.module.pypyjit.interp_jit import pypyjitdriver
 
 class Cache(object):
     in_recursion = False
@@ -111,13 +113,24 @@
 
 def wrap_oplist(space, logops, operations, ops_offset=None):
     l_w = []
+    jitdrivers_sd = logops.metainterp_sd.jitdrivers_sd
     for op in operations:
         if ops_offset is None:
             ofs = -1
         else:
             ofs = ops_offset.get(op, 0)
-        l_w.append(WrappedOp(jit_hooks._cast_to_gcref(op), ofs,
-                             logops.repr_of_resop(op)))
+        if op.opnum == rop.DEBUG_MERGE_POINT:
+            jd_sd = jitdrivers_sd[op.getarg(0).getint()]
+            greenkey = op.getarglist()[2:]
+            repr = jd_sd.warmstate.get_location_str(greenkey)
+            w_greenkey = wrap_greenkey(space, jd_sd.jitdriver, greenkey, repr)
+            l_w.append(DebugMergePoint(space, jit_hooks._cast_to_gcref(op),
+                                       logops.repr_of_resop(op),
+                                       jd_sd.jitdriver.name,
+                                       w_greenkey))
+        else:
+            l_w.append(WrappedOp(jit_hooks._cast_to_gcref(op), ofs,
+                                 logops.repr_of_resop(op)))
     return l_w
 
 class WrappedBox(Wrappable):
@@ -150,6 +163,15 @@
         llres = res.llbox
     return WrappedOp(jit_hooks.resop_new(num, args, llres), offset, repr)
 
+ at unwrap_spec(repr=str, jd_name=str)
+def descr_new_dmp(space, w_tp, w_args, repr, jd_name, w_greenkey):
+    args = [space.interp_w(WrappedBox, w_arg).llbox for w_arg in
+            space.listview(w_args)]
+    num = rop.DEBUG_MERGE_POINT
+    return DebugMergePoint(space,
+                           jit_hooks.resop_new(num, args, jit_hooks.emptyval()),
+                           repr, jd_name, w_greenkey)
+
 class WrappedOp(Wrappable):
     """ A class representing a single ResOperation, wrapped nicely
     """
@@ -182,6 +204,25 @@
         box = space.interp_w(WrappedBox, w_box)
         jit_hooks.resop_setresult(self.op, box.llbox)
 
+class DebugMergePoint(WrappedOp):
+    def __init__(self, space, op, repr_of_resop, jd_name, w_greenkey):
+        WrappedOp.__init__(self, op, -1, repr_of_resop)
+        self.w_greenkey = w_greenkey
+        self.jd_name = jd_name
+
+    def get_pycode(self, space):
+        if self.jd_name == pypyjitdriver.name:
+            return space.getitem(self.w_greenkey, space.wrap(0))
+        raise OperationError(space.w_AttributeError, space.wrap("This DebugMergePoint doesn't belong to the main Python JitDriver"))
+
+    def get_bytecode_no(self, space):
+        if self.jd_name == pypyjitdriver.name:
+            return space.getitem(self.w_greenkey, space.wrap(1))
+        raise OperationError(space.w_AttributeError, space.wrap("This DebugMergePoint doesn't belong to the main Python JitDriver"))
+
+    def get_jitdriver_name(self, space):
+        return space.wrap(self.jd_name)
+
 WrappedOp.typedef = TypeDef(
     'ResOperation',
     __doc__ = WrappedOp.__doc__,
@@ -195,3 +236,15 @@
                             WrappedOp.descr_setresult)
 )
 WrappedOp.acceptable_as_base_class = False
+
+DebugMergePoint.typedef = TypeDef(
+    'DebugMergePoint', WrappedOp.typedef,
+    __new__ = interp2app(descr_new_dmp),
+    greenkey = interp_attrproperty_w("w_greenkey", cls=DebugMergePoint),
+    pycode = GetSetProperty(DebugMergePoint.get_pycode),
+    bytecode_no = GetSetProperty(DebugMergePoint.get_bytecode_no),
+    jitdriver_name = GetSetProperty(DebugMergePoint.get_jitdriver_name),
+)
+DebugMergePoint.acceptable_as_base_class = False
+
+
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -127,7 +127,7 @@
                        'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
                        'posix', '_socket', '_sre', '_lsprof', '_weakref',
                        '__pypy__', 'cStringIO', '_collections', 'struct',
-                       'mmap', 'marshal']:
+                       'mmap', 'marshal', '_codecs']:
             if modname == 'pypyjit' and 'interp_resop' in rest:
                 return False
             return True
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -92,6 +92,7 @@
         cls.w_on_compile_bridge = space.wrap(interp2app(interp_on_compile_bridge))
         cls.w_on_abort = space.wrap(interp2app(interp_on_abort))
         cls.w_int_add_num = space.wrap(rop.INT_ADD)
+        cls.w_dmp_num = space.wrap(rop.DEBUG_MERGE_POINT)
         cls.w_on_optimize = space.wrap(interp2app(interp_on_optimize))
         cls.orig_oplist = oplist
 
@@ -117,6 +118,10 @@
         assert elem[2][2] == False
         assert len(elem[3]) == 4
         int_add = elem[3][0]
+        dmp = elem[3][1]
+        assert isinstance(dmp, pypyjit.DebugMergePoint)
+        assert dmp.pycode is self.f.func_code
+        assert dmp.greenkey == (self.f.func_code, 0, False)
         #assert int_add.name == 'int_add'
         assert int_add.num == self.int_add_num
         self.on_compile_bridge()
@@ -211,3 +216,18 @@
         assert op.getarg(0).getint() == 4
         op.result = box
         assert op.result.getint() == 1
+
+    def test_creation_dmp(self):
+        from pypyjit import DebugMergePoint, Box
+
+        def f():
+            pass
+
+        op = DebugMergePoint([Box(0)], 'repr', 'pypyjit', (f.func_code, 0, 0))
+        assert op.bytecode_no == 0
+        assert op.pycode is f.func_code
+        assert repr(op) == 'repr'
+        assert op.jitdriver_name == 'pypyjit'
+        assert op.num == self.dmp_num
+        op = DebugMergePoint([Box(0)], 'repr', 'notmain', ('str',))
+        raises(AttributeError, 'op.pycode')
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
 CPYTHON_VERSION            = (2, 7, 1, "final", 42)   #XXX # sync patchlevel.h
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (1, 7, 1, "dev", 0)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (1, 8, 1, "dev", 0)    #XXX # sync patchlevel.h
 
 if platform.name == 'msvc':
     COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/lib_pypy/numpypy/test/test_fromnumeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
rename from lib_pypy/numpypy/test/test_fromnumeric.py
rename to pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
--- a/lib_pypy/numpypy/test/test_fromnumeric.py
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
@@ -1,7 +1,7 @@
-
 from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
 
-class AppTestFromNumeric(BaseNumpyAppTest):     
+
+class AppTestFromNumeric(BaseNumpyAppTest):
     def test_argmax(self):
         # tests taken from numpy/core/fromnumeric.py docstring
         from numpypy import array, arange, argmax
@@ -18,12 +18,12 @@
         from numpypy import array, arange, argmin
         a = arange(6).reshape((2,3))
         assert argmin(a) == 0
-        # assert (argmax(a, axis=0) == array([0, 0, 0])).all()
-        # assert (argmax(a, axis=1) == array([0, 0])).all()
+        assert (argmin(a, axis=0) == array([0, 0, 0])).all()
+        assert (argmin(a, axis=1) == array([0, 0])).all()
         b = arange(6)
         b[1] = 0
         assert argmin(b) == 0
-   
+
     def test_shape(self):
         # tests taken from numpy/core/fromnumeric.py docstring
         from numpypy import array, identity, shape
@@ -44,7 +44,7 @@
         # assert (sum([[0, 1], [0, 5]], axis=1) == array([1, 5])).all()
         # If the accumulator is too small, overflow occurs:
         # assert ones(128, dtype=int8).sum(dtype=int8) == -128
-                                 
+
     def test_amin(self):
         # tests taken from numpy/core/fromnumeric.py docstring
         from numpypy import array, arange, amin
@@ -86,14 +86,14 @@
         assert ndim([[1,2,3],[4,5,6]]) == 2
         assert ndim(array([[1,2,3],[4,5,6]])) == 2
         assert ndim(1) == 0
-    
+
     def test_rank(self):
         # tests taken from numpy/core/fromnumeric.py docstring
         from numpypy import array, rank
         assert rank([[1,2,3],[4,5,6]]) == 2
         assert rank(array([[1,2,3],[4,5,6]])) == 2
         assert rank(1) == 0
-    
+
     def test_var(self):
         from numpypy import array, var
         a = array([[1,2],[3,4]])
@@ -107,3 +107,31 @@
         assert std(a) ==  1.1180339887498949
         # assert (std(a, axis=0) == array([ 1.,  1.])).all()
         # assert (std(a, axis=1) == array([ 0.5,  0.5]).all()
+
+    def test_mean(self):
+        from numpypy import array, mean
+        assert mean(array(range(5))) == 2.0
+        assert mean(range(5)) == 2.0
+
+    def test_reshape(self):
+        from numpypy import arange, array, dtype, reshape
+        a = arange(12)
+        b = reshape(a, (3, 4))
+        assert b.shape == (3, 4)
+        a = range(12)
+        b = reshape(a, (3, 4))
+        assert b.shape == (3, 4)
+        a = array(range(105)).reshape(3, 5, 7)
+        assert reshape(a, (1, -1)).shape == (1, 105)
+        assert reshape(a, (1, 1, -1)).shape == (1, 1, 105)
+        assert reshape(a, (-1, 1, 1)).shape == (105, 1, 1)
+    
+    def test_transpose(self):   
+        from numpypy import arange, array, transpose, ones
+        x = arange(4).reshape((2,2))
+        assert (transpose(x) == array([[0, 2],[1, 3]])).all()
+        # Once axes argument is implemented, add more tests
+        raises(NotImplementedError, "transpose(x, axes=(1, 0, 2))")
+        # x = ones((1, 2, 3))
+        # assert transpose(x, (1, 0, 2)).shape == (2, 1, 3)
+
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -64,6 +64,12 @@
         check(', '.join([u'a']), u'a')
         check(', '.join(['a', u'b']), u'a, b')
         check(u', '.join(['a', 'b']), u'a, b')
+        try:
+            u''.join([u'a', 2, 3])
+        except TypeError, e:
+            assert 'sequence item 1' in str(e)
+        else:
+            raise Exception("DID NOT RAISE")
 
     if sys.version_info >= (2,3):
         def test_contains_ex(self):
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -201,7 +201,7 @@
     return space.newbool(container.find(item) != -1)
 
 def unicode_join__Unicode_ANY(space, w_self, w_list):
-    list_w = space.unpackiterable(w_list)
+    list_w = space.listview(w_list)
     size = len(list_w)
 
     if size == 0:
@@ -216,22 +216,21 @@
 
 def _unicode_join_many_items(space, w_self, list_w, size):
     self = w_self._value
-    sb = UnicodeBuilder()
+    prealloc_size = len(self) * (size - 1)
+    for i in range(size):
+        try:
+            prealloc_size += len(space.unicode_w(list_w[i]))
+        except OperationError, e:
+            if not e.match(space, space.w_TypeError):
+                raise
+            raise operationerrfmt(space.w_TypeError,
+                        "sequence item %d: expected string or Unicode", i)
+    sb = UnicodeBuilder(prealloc_size)
     for i in range(size):
         if self and i != 0:
             sb.append(self)
         w_s = list_w[i]
-        if isinstance(w_s, W_UnicodeObject):
-            # shortcut for performance
-            sb.append(w_s._value)
-        else:
-            try:
-                sb.append(space.unicode_w(w_s))
-            except OperationError, e:
-                if not e.match(space, space.w_TypeError):
-                    raise
-                raise operationerrfmt(space.w_TypeError,
-                    "sequence item %d: expected string or Unicode", i)
+        sb.append(space.unicode_w(w_s))
     return space.wrap(sb.build())
 
 def hash__Unicode(space, w_uni):
diff --git a/pypy/rlib/jit_hooks.py b/pypy/rlib/jit_hooks.py
--- a/pypy/rlib/jit_hooks.py
+++ b/pypy/rlib/jit_hooks.py
@@ -52,7 +52,10 @@
     from pypy.jit.metainterp.history import ResOperation
 
     args = [_cast_to_box(llargs[i]) for i in range(len(llargs))]
-    res = _cast_to_box(llres)
+    if llres:
+        res = _cast_to_box(llres)
+    else:
+        res = None
     return _cast_to_gcref(ResOperation(no, args, res))
 
 @register_helper(annmodel.SomePtr(llmemory.GCREF))
diff --git a/pypy/rlib/longlong2float.py b/pypy/rlib/longlong2float.py
--- a/pypy/rlib/longlong2float.py
+++ b/pypy/rlib/longlong2float.py
@@ -79,19 +79,23 @@
 longlong2float = rffi.llexternal(
     "pypy__longlong2float", [rffi.LONGLONG], rffi.DOUBLE,
     _callable=longlong2float_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True, sandboxsafe=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True,
+    oo_primitive="pypy__longlong2float")
 
 float2longlong = rffi.llexternal(
     "pypy__float2longlong", [rffi.DOUBLE], rffi.LONGLONG,
     _callable=float2longlong_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True, sandboxsafe=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True,
+    oo_primitive="pypy__float2longlong")
 
 uint2singlefloat = rffi.llexternal(
     "pypy__uint2singlefloat", [rffi.UINT], rffi.FLOAT,
     _callable=uint2singlefloat_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True, sandboxsafe=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True,
+    oo_primitive="pypy__uint2singlefloat")
 
 singlefloat2uint = rffi.llexternal(
     "pypy__singlefloat2uint", [rffi.FLOAT], rffi.UINT,
     _callable=singlefloat2uint_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True, sandboxsafe=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True,
+    oo_primitive="pypy__singlefloat2uint")
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -420,7 +420,7 @@
                   vobj.concretetype.TO._gckind == 'gc')
         else:
             from pypy.rpython.ootypesystem import ootype
-            ok = isinstance(vobj.concretetype, ootype.Instance)
+            ok = isinstance(vobj.concretetype, (ootype.Instance, ootype.BuiltinType))
         if not ok:
             from pypy.rpython.error import TyperError
             raise TyperError("compute_unique_id() cannot be applied to"
diff --git a/pypy/rpython/lltypesystem/rclass.py b/pypy/rpython/lltypesystem/rclass.py
--- a/pypy/rpython/lltypesystem/rclass.py
+++ b/pypy/rpython/lltypesystem/rclass.py
@@ -510,7 +510,13 @@
         ctype = inputconst(Void, self.object_type)
         cflags = inputconst(Void, flags)
         vlist = [ctype, cflags]
-        vptr = llops.genop('malloc', vlist,
+        cnonmovable = self.classdef.classdesc.read_attribute(
+            '_alloc_nonmovable_', Constant(False))
+        if cnonmovable.value:
+            opname = 'malloc_nonmovable'
+        else:
+            opname = 'malloc'
+        vptr = llops.genop(opname, vlist,
                            resulttype = Ptr(self.object_type))
         ctypeptr = inputconst(CLASSTYPE, self.rclass.getvtable())
         self.setfield(vptr, '__class__', ctypeptr, llops)
diff --git a/pypy/rpython/lltypesystem/rtuple.py b/pypy/rpython/lltypesystem/rtuple.py
--- a/pypy/rpython/lltypesystem/rtuple.py
+++ b/pypy/rpython/lltypesystem/rtuple.py
@@ -27,6 +27,10 @@
 
     def newtuple(cls, llops, r_tuple, items_v):
         # items_v should have the lowleveltype of the internal reprs
+        assert len(r_tuple.items_r) == len(items_v)
+        for r_item, v_item in zip(r_tuple.items_r, items_v):
+            assert r_item.lowleveltype == v_item.concretetype
+        #
         if len(r_tuple.items_r) == 0:
             return inputconst(Void, ())    # a Void empty tuple
         c1 = inputconst(Void, r_tuple.lowleveltype.TO)
diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py
--- a/pypy/rpython/ootypesystem/ootype.py
+++ b/pypy/rpython/ootypesystem/ootype.py
@@ -512,6 +512,7 @@
             "ll_append_char": Meth([CHARTP], Void),
             "ll_append": Meth([STRINGTP], Void),
             "ll_build": Meth([], STRINGTP),
+            "ll_getlength": Meth([], Signed),
             })
         self._setup_methods({})
 
@@ -1376,6 +1377,9 @@
     def _cast_to_object(self):
         return make_object(self)
 
+    def _identityhash(self):
+        return object.__hash__(self)
+
 class _string(_builtin_type):
 
     def __init__(self, STRING, value = ''):
@@ -1543,6 +1547,9 @@
         else:
             return make_unicode(u''.join(self._buf))
 
+    def ll_getlength(self):
+        return self.ll_build().ll_strlen()
+
 class _null_string_builder(_null_mixin(_string_builder), _string_builder):
     def __init__(self, STRING_BUILDER):
         self.__dict__["_TYPE"] = STRING_BUILDER
diff --git a/pypy/rpython/ootypesystem/rbuilder.py b/pypy/rpython/ootypesystem/rbuilder.py
--- a/pypy/rpython/ootypesystem/rbuilder.py
+++ b/pypy/rpython/ootypesystem/rbuilder.py
@@ -21,6 +21,10 @@
         builder.ll_append_char(char)
 
     @staticmethod
+    def ll_getlength(builder):
+        return builder.ll_getlength()
+
+    @staticmethod
     def ll_append(builder, string):
         builder.ll_append(string)
 
diff --git a/pypy/rpython/rrange.py b/pypy/rpython/rrange.py
--- a/pypy/rpython/rrange.py
+++ b/pypy/rpython/rrange.py
@@ -204,7 +204,10 @@
         v_index = hop.gendirectcall(self.ll_getnextindex, v_enumerate)
         hop2 = hop.copy()
         hop2.args_r = [self.r_baseiter]
+        r_item_src = self.r_baseiter.r_list.external_item_repr
+        r_item_dst = hop.r_result.items_r[1]
         v_item = self.r_baseiter.rtype_next(hop2)
+        v_item = hop.llops.convertvar(v_item, r_item_src, r_item_dst)
         return hop.r_result.newtuple(hop.llops, hop.r_result,
                                      [v_index, v_item])
 
diff --git a/pypy/rpython/test/test_rbuilder.py b/pypy/rpython/test/test_rbuilder.py
--- a/pypy/rpython/test/test_rbuilder.py
+++ b/pypy/rpython/test/test_rbuilder.py
@@ -124,9 +124,5 @@
     pass
 
 class TestOOtype(BaseTestStringBuilder, OORtypeMixin):
-    def test_string_getlength(self):
-        py.test.skip("getlength(): not implemented on ootype")
-    def test_unicode_getlength(self):
-        py.test.skip("getlength(): not implemented on ootype")
     def test_append_charpsize(self):
         py.test.skip("append_charpsize(): not implemented on ootype")
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -463,6 +463,31 @@
             assert x1 == intmask(x0)
             assert x3 == intmask(x2)
 
+    def test_id_on_builtins(self):
+        from pypy.rlib.objectmodel import compute_unique_id
+        from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+        def fn():
+            return (compute_unique_id("foo"),
+                    compute_unique_id(u"bar"),
+                    compute_unique_id([1]),
+                    compute_unique_id({"foo": 3}),
+                    compute_unique_id(StringBuilder()),
+                    compute_unique_id(UnicodeBuilder()))
+        res = self.interpret(fn, [])
+        for id in self.ll_unpack_tuple(res, 6):
+            assert isinstance(id, (int, r_longlong))
+
+    def test_uniqueness_of_id_on_strings(self):
+        from pypy.rlib.objectmodel import compute_unique_id
+        def fn(s1, s2):
+            return (compute_unique_id(s1), compute_unique_id(s2))
+
+        s1 = "foo"
+        s2 = ''.join(['f','oo'])
+        res = self.interpret(fn, [self.string_to_ll(s1), self.string_to_ll(s2)])
+        i1, i2 = self.ll_unpack_tuple(res, 2)
+        assert i1 != i2
+
     def test_cast_primitive(self):
         from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
         def llf(u):
diff --git a/pypy/rpython/test/test_rclass.py b/pypy/rpython/test/test_rclass.py
--- a/pypy/rpython/test/test_rclass.py
+++ b/pypy/rpython/test/test_rclass.py
@@ -1130,6 +1130,18 @@
             assert sorted([u]) == [6]                    # 32-bit types
             assert sorted([i, r, d, l]) == [2, 3, 4, 5]  # 64-bit types
 
+    def test_nonmovable(self):
+        for (nonmovable, opname) in [(True, 'malloc_nonmovable'),
+                                     (False, 'malloc')]:
+            class A(object):
+                _alloc_nonmovable_ = nonmovable
+            def f():
+                return A()
+            t, typer, graph = self.gengraph(f, [])
+            assert summary(graph) == {opname: 1,
+                                      'cast_pointer': 1,
+                                      'setfield': 1}
+
 
 class TestOOtype(BaseTestRclass, OORtypeMixin):
 
diff --git a/pypy/rpython/test/test_rrange.py b/pypy/rpython/test/test_rrange.py
--- a/pypy/rpython/test/test_rrange.py
+++ b/pypy/rpython/test/test_rrange.py
@@ -169,6 +169,22 @@
         res = self.interpret(fn, [2])
         assert res == 789
 
+    def test_enumerate_instances(self):
+        class A:
+            pass
+        def fn(n):
+            a = A()
+            b = A()
+            a.k = 10
+            b.k = 20
+            for i, x in enumerate([a, b]):
+                if i == n:
+                    return x.k
+            return 5
+        res = self.interpret(fn, [1])
+        assert res == 20
+
+
 
 class TestLLtype(BaseTestRrange, LLRtypeMixin):
     from pypy.rpython.lltypesystem import rrange 
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -140,13 +140,15 @@
     bytecode_name = None
     is_bytecode = True
     inline_level = None
+    has_dmp = False
 
     def parse_code_data(self, arg):
         m = re.search('<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] line (\d+)> #(\d+) (\w+)',
                       arg)
         if m is None:
             # a non-code loop, like StrLiteralSearch or something
-            self.bytecode_name = arg
+            if arg:
+                self.bytecode_name = arg
         else:
             self.name, self.filename, lineno, bytecode_no, self.bytecode_name = m.groups()
             self.startlineno = int(lineno)
@@ -218,7 +220,7 @@
         self.inputargs = inputargs
         self.chunks = chunks
         for chunk in self.chunks:
-            if chunk.filename is not None:
+            if chunk.bytecode_name is not None:
                 self.startlineno = chunk.startlineno
                 self.filename = chunk.filename
                 self.name = chunk.name
diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -283,3 +283,13 @@
     assert loops[-1].count == 1234
     assert loops[1].count == 123
     assert loops[2].count == 12
+
+def test_parse_nonpython():
+    loop = parse("""
+    []
+    debug_merge_point(0, 'random')
+    debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
+    """)
+    f = Function.from_operations(loop.operations, LoopStorage())
+    assert f.chunks[-1].filename == 'x.py'
+    assert f.filename is None
diff --git a/pypy/translator/jvm/builtin.py b/pypy/translator/jvm/builtin.py
--- a/pypy/translator/jvm/builtin.py
+++ b/pypy/translator/jvm/builtin.py
@@ -84,6 +84,9 @@
     (ootype.StringBuilder.__class__, "ll_build"):
     jvm.Method.v(jStringBuilder, "toString", (), jString),
 
+    (ootype.StringBuilder.__class__, "ll_getlength"):
+    jvm.Method.v(jStringBuilder, "length", (), jInt),
+
     (ootype.String.__class__, "ll_hash"):
     jvm.Method.v(jString, "hashCode", (), jInt),
 
diff --git a/pypy/translator/jvm/database.py b/pypy/translator/jvm/database.py
--- a/pypy/translator/jvm/database.py
+++ b/pypy/translator/jvm/database.py
@@ -358,7 +358,7 @@
         ootype.Unsigned:jvm.PYPYSERIALIZEUINT,
         ootype.SignedLongLong:jvm.LONGTOSTRINGL,
         ootype.UnsignedLongLong: jvm.PYPYSERIALIZEULONG,
-        ootype.Float:jvm.DOUBLETOSTRINGD,
+        ootype.Float:jvm.PYPYSERIALIZEDOUBLE,
         ootype.Bool:jvm.PYPYSERIALIZEBOOLEAN,
         ootype.Void:jvm.PYPYSERIALIZEVOID,
         ootype.Char:jvm.PYPYESCAPEDCHAR,
diff --git a/pypy/translator/jvm/metavm.py b/pypy/translator/jvm/metavm.py
--- a/pypy/translator/jvm/metavm.py
+++ b/pypy/translator/jvm/metavm.py
@@ -92,6 +92,7 @@
 CASTS = {
 #   FROM                      TO
     (ootype.Signed,           ootype.UnsignedLongLong): jvm.I2L,
+    (ootype.Unsigned,         ootype.UnsignedLongLong): jvm.I2L,
     (ootype.SignedLongLong,   ootype.Signed):           jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Unsigned):         jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Signed):           jvm.L2I,
diff --git a/pypy/translator/jvm/opcodes.py b/pypy/translator/jvm/opcodes.py
--- a/pypy/translator/jvm/opcodes.py
+++ b/pypy/translator/jvm/opcodes.py
@@ -101,6 +101,7 @@
     'jit_force_virtualizable':  Ignore,
     'jit_force_virtual':        DoNothing,
     'jit_force_quasi_immutable': Ignore,
+    'jit_is_virtual':           PushPrimitive(ootype.Bool, False),
 
     'debug_assert':              [], # TODO: implement?
     'debug_start_traceback':    Ignore,
diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -283,6 +283,14 @@
         }
     }
 
+    public double pypy__longlong2float(long l) {
+        return Double.longBitsToDouble(l);
+    }
+
+    public long pypy__float2longlong(double d) {
+        return Double.doubleToRawLongBits(d);
+    }
+
     public double ooparse_float(String s) {
         try {
             return Double.parseDouble(s);
@@ -353,6 +361,19 @@
             return "False";
     }
 
+    public static String serialize_double(double d) {
+        if (Double.isNaN(d)) {
+            return "float(\"nan\")";
+        } else if (Double.isInfinite(d)) {
+            if (d > 0)
+                return "float(\"inf\")";
+            else
+                return "float(\"-inf\")";
+        } else {
+            return Double.toString(d);
+        }
+    }
+
     private static String format_char(char c) {
         String res = "\\x";
         if (c <= 0x0F) res = res + "0";
diff --git a/pypy/translator/jvm/test/runtest.py b/pypy/translator/jvm/test/runtest.py
--- a/pypy/translator/jvm/test/runtest.py
+++ b/pypy/translator/jvm/test/runtest.py
@@ -56,6 +56,7 @@
 
 # CLI could-be duplicate
 class JvmGeneratedSourceWrapper(object):
+
     def __init__(self, gensrc):
         """ gensrc is an instance of JvmGeneratedSource """
         self.gensrc = gensrc
diff --git a/pypy/translator/jvm/test/test_builder.py b/pypy/translator/jvm/test/test_builder.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/jvm/test/test_builder.py
@@ -0,0 +1,7 @@
+from pypy.translator.jvm.test.runtest import JvmTest
+from pypy.rpython.test.test_rbuilder import BaseTestStringBuilder
+import py
+
+class TestJvmStringBuilder(JvmTest, BaseTestStringBuilder):
+    def test_append_charpsize(self):
+        py.test.skip("append_charpsize(): not implemented on ootype")
diff --git a/pypy/translator/jvm/test/test_longlong2float.py b/pypy/translator/jvm/test/test_longlong2float.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/jvm/test/test_longlong2float.py
@@ -0,0 +1,20 @@
+from pypy.translator.jvm.test.runtest import JvmTest
+from pypy.rlib.longlong2float import *
+from pypy.rlib.test.test_longlong2float import enum_floats
+from pypy.rlib.test.test_longlong2float import fn as float2longlong2float
+import py
+
+class TestLongLong2Float(JvmTest):
+
+    def test_float2longlong_and_longlong2float(self):
+        def func(f):
+            return float2longlong2float(f)
+
+        for f in enum_floats():
+            assert repr(f) == repr(self.interpret(func, [f]))
+
+    def test_uint2singlefloat(self):
+        py.test.skip("uint2singlefloat is not implemented in ootype")
+
+    def test_singlefloat2uint(self):
+        py.test.skip("singlefloat2uint is not implemented in ootype")
diff --git a/pypy/translator/jvm/typesystem.py b/pypy/translator/jvm/typesystem.py
--- a/pypy/translator/jvm/typesystem.py
+++ b/pypy/translator/jvm/typesystem.py
@@ -955,6 +955,7 @@
 PYPYSERIALIZEUINT  =    Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
 PYPYSERIALIZEULONG =    Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString)
 PYPYSERIALIZEVOID =     Method.s(jPyPy, 'serialize_void', (), jString)
+PYPYSERIALIZEDOUBLE =   Method.s(jPyPy, 'serialize_double', (jDouble,), jString)
 PYPYESCAPEDCHAR =       Method.s(jPyPy, 'escaped_char', (jChar,), jString)
 PYPYESCAPEDUNICHAR =    Method.s(jPyPy, 'escaped_unichar', (jChar,), jString)
 PYPYESCAPEDSTRING =     Method.s(jPyPy, 'escaped_string', (jString,), jString)
diff --git a/pypy/translator/oosupport/test_template/cast.py b/pypy/translator/oosupport/test_template/cast.py
--- a/pypy/translator/oosupport/test_template/cast.py
+++ b/pypy/translator/oosupport/test_template/cast.py
@@ -13,6 +13,9 @@
 def to_longlong(x):
     return r_longlong(x)
 
+def to_ulonglong(x):
+    return r_ulonglong(x)
+
 def uint_to_int(x):
     return intmask(x)
 
@@ -56,6 +59,9 @@
     def test_unsignedlonglong_to_unsigned4(self):
         self.check(to_uint, [r_ulonglong(18446744073709551615l)]) # max 64 bit num
 
+    def test_unsigned_to_usignedlonglong(self):
+        self.check(to_ulonglong, [r_uint(42)])
+
     def test_uint_to_int(self):
         self.check(uint_to_int, [r_uint(sys.maxint+1)])
 


More information about the pypy-commit mailing list