[pypy-commit] pypy more-rposix: hg merge default

amauryfa noreply at buildbot.pypy.org
Sun May 3 18:37:49 CEST 2015


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: more-rposix
Changeset: r77004:bbd40bb55e9d
Date: 2015-04-23 23:28 +0200
http://bitbucket.org/pypy/pypy/changeset/bbd40bb55e9d/

Log:	hg merge default

diff too long, truncating to 2000 out of 6881 lines

diff --git a/.tddium.requirements.txt b/.tddium.requirements.txt
deleted file mode 100644
--- a/.tddium.requirements.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-pytest
diff --git a/lib-python/2.7/test/test_urllib2net.py b/lib-python/2.7/test/test_urllib2net.py
--- a/lib-python/2.7/test/test_urllib2net.py
+++ b/lib-python/2.7/test/test_urllib2net.py
@@ -102,11 +102,8 @@
 
     def test_ftp(self):
         urls = [
-            'ftp://ftp.kernel.org/pub/linux/kernel/README',
-            'ftp://ftp.kernel.org/pub/linux/kernel/non-existent-file',
-            #'ftp://ftp.kernel.org/pub/leenox/kernel/test',
-            'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
-                '/research-reports/00README-Legal-Rules-Regs',
+            'ftp://ftp.debian.org/debian/README',
+            'ftp://ftp.debian.org/debian/non-existent-file',
             ]
         self._test_urls(urls, self._extra_handlers())
 
@@ -255,6 +252,7 @@
         with test_support.transient_internet(url, timeout=None):
             u = _urlopen_with_retry(url)
             self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+            u.close()
 
     def test_http_default_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -266,6 +264,7 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60)
+            u.close()
 
     def test_http_no_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -277,20 +276,23 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+            u.close()
 
     def test_http_timeout(self):
         url = "http://www.example.com"
         with test_support.transient_internet(url):
             u = _urlopen_with_retry(url, timeout=120)
             self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
+            u.close()
 
-    FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/"
+    FTP_HOST = 'ftp://ftp.debian.org/debian/'
 
     def test_ftp_basic(self):
         self.assertIsNone(socket.getdefaulttimeout())
         with test_support.transient_internet(self.FTP_HOST, timeout=None):
             u = _urlopen_with_retry(self.FTP_HOST)
             self.assertIsNone(u.fp.fp._sock.gettimeout())
+            u.close()
 
     def test_ftp_default_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -301,6 +303,7 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+            u.close()
 
     def test_ftp_no_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout(),)
@@ -311,11 +314,16 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertIsNone(u.fp.fp._sock.gettimeout())
+            u.close()
 
     def test_ftp_timeout(self):
         with test_support.transient_internet(self.FTP_HOST):
-            u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+            try:
+                u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+            except:
+                raise
             self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+            u.close()
 
 
 def test_main():
diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py
--- a/lib_pypy/_tkinter/tklib.py
+++ b/lib_pypy/_tkinter/tklib.py
@@ -1,7 +1,7 @@
 # C bindings with libtcl and libtk.
 
 from cffi import FFI
-import sys
+import sys, os
 
 tkffi = FFI()
 
@@ -135,9 +135,12 @@
     linklibs = ['tcl', 'tk']
     libdirs = []
 else:
-    incdirs=['/usr/include/tcl']
-    linklibs=['tcl', 'tk']
-    libdirs = []
+    for _ver in ['', '8.6', '8.5', '']:
+        incdirs = ['/usr/include/tcl' + _ver]
+        linklibs = ['tcl' + _ver, 'tk' + _ver]
+        libdirs = []
+        if os.path.isdir(incdirs[0]):
+            break
 
 tklib = tkffi.verify("""
 #include <tcl.h>
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -33,6 +33,16 @@
         return False
     return True
 
+def _strip_final_indent(text):
+    # kill spaces and tabs at the end, but only if they follow '\n'.
+    # meant to remove the auto-indentation only (although it would of
+    # course also remove explicitly-added indentation).
+    short = text.rstrip(' \t')
+    n = len(short)
+    if n > 0 and text[n-1] == '\n':
+        return short
+    return text
+
 def run_multiline_interactive_console(mainmodule=None):
     import code
     if mainmodule is None:
@@ -41,7 +51,7 @@
 
     def more_lines(unicodetext):
         # ooh, look at the hack:
-        src = "#coding:utf-8\n"+unicodetext.encode('utf-8')
+        src = "#coding:utf-8\n"+_strip_final_indent(unicodetext).encode('utf-8')
         try:
             code = console.compile(src, '<stdin>', 'single')
         except (OverflowError, SyntaxError, ValueError):
@@ -58,7 +68,7 @@
                                             returns_unicode=True)
             except EOFError:
                 break
-            more = console.push(statement)
+            more = console.push(_strip_final_indent(statement))
             assert not more
         except KeyboardInterrupt:
             console.write("\nKeyboardInterrupt\n")
diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.rst
+++ b/pypy/doc/getting-started-dev.rst
@@ -207,12 +207,17 @@
 large amount of options that can be used to customize pyinteractive.py).
 As an example of using PyPy from the command line, you could type::
 
-    python pyinteractive.py -c "from test import pystone; pystone.main(10)"
+    python pyinteractive.py --withmod-time -c "from test import pystone; pystone.main(10)"
 
 Alternatively, as with regular Python, you can simply give a
 script name on the command line::
 
-    python pyinteractive.py ../../lib-python/2.7/test/pystone.py 10
+    python pyinteractive.py --withmod-time ../../lib-python/2.7/test/pystone.py 10
+
+The ``--withmod-xxx`` option enables the built-in module ``xxx``.  By
+default almost none of them are, because initializing them takes time.
+If you want anyway to enable all built-in modules, you can use
+``--allworkingmodules``.
 
 See our :doc:`configuration sections <config/index>` for details about what all the commandline
 options do.
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,9 +5,65 @@
 .. this is a revision shortly after release-2.5.1
 .. startrev: cb01edcb59414d9d93056e54ed060673d24e67c1
 
+issue2005:
+ignore errors on closing random file handles while importing a module (cpython compatibility)
+
+issue2013:
+added constants to _ssl for TLS 1.1 and 1.2
+
+issue2014:
+Add PyLong_FromUnicode to cpyext.
+
+issue2017: 
+On non-Linux-x86 platforms, reduced the memory impact of
+creating a lot of greenlets/tasklets.  Particularly useful on Win32 and
+on ARM, where you used to get a MemoryError after only 2500-5000
+greenlets (the 32-bit address space is exhausted).
+
+Update gdb_pypy for python3 (gdb comatability)
+
+Merged rstrategies into rpython which provides a library for Storage Strategies
+
+Support unicode strings in numpy.dtype creation i.e. np.dtype(u'int64')
+
+Various rpython cleanups for vmprof support
+
+issue2019:
+Fix isspace as called by rpython unicode.strip()
+
+issue2023:
+In the cpyext 'Concrete Object Layer' API,
+don't call methods on the object (which can be overriden),
+but directly on the concrete base type.
+
+issue2029:
+Hide the default_factory attribute in a dict
+
+issue2027:
+Better document pyinteractive and add --withmod-time
+
 .. branch: gc-incminimark-pinning-improve
+
+branch gc-incminimark-pinning-improve: 
 Object Pinning is now used in `bz2` and `rzlib` (therefore also affects
 Python's `zlib`). In case the data to compress/decompress is inside the nursery
 (incminimark) it no longer needs to create a non-moving copy of it. This saves
 one `malloc` and copying the data.  Additionally a new GC environment variable
 is introduced (`PYPY_GC_MAX_PINNED`) primarily for debugging purposes.
+
+.. branch: refactor-pycall
+
+branch refactor-pycall:
+Make `*`-unpacking in RPython function calls completely equivalent to passing
+the tuple's elements as arguments. In other words, `f(*(a, b))` now behaves 
+exactly like `f(a, b)`.
+
+.. branch: issue2018
+branch issue2018:
+Allow prebuilt rpython dict with function values
+
+.. branch: vmprof
+.. Merged but then backed out, hopefully it will return as vmprof2
+
+.. branch: object-dtype2
+Extend numpy dtypes to allow using objects with associated garbage collection hook
diff --git a/pypy/goal/targetnumpystandalone.py b/pypy/goal/targetnumpystandalone.py
deleted file mode 100644
--- a/pypy/goal/targetnumpystandalone.py
+++ /dev/null
@@ -1,43 +0,0 @@
-
-""" Usage:
-
-./targetnumpystandalone-c <bytecode> array_size
-
-Will execute a give numpy bytecode. Arrays will be ranges (in float) modulo 10,
-constants would be consecutive starting from one.
-
-Bytecode should contain letters 'a' 'l' and 'f' so far and be correct
-"""
-
-import time
-from pypy.module.micronumpy.compile import numpy_compile
-from rpython.jit.codewriter.policy import JitPolicy
-from rpython.rtyper.annlowlevel import hlstr
-
-def entry_point(argv):
-    if len(argv) != 3:
-        print __doc__
-        return 1
-    try:
-        size = int(argv[2])
-    except ValueError:
-        print "INVALID LITERAL FOR INT:", argv[2]
-        print __doc__
-        return 3
-    t0 = time.time()
-    main(argv[0], size)
-    print "bytecode:", argv[0], "size:", size
-    print "took:", time.time() - t0
-    return 0
-
-def main(bc, size):
-    if not isinstance(bc, str):
-        bc = hlstr(bc) # for tests
-    a = numpy_compile(bc, size)
-    a = a.compute()
-
-def target(*args):
-    return entry_point, None
-
-def jitpolicy(driver):
-    return JitPolicy()
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -1,5 +1,6 @@
 """Python control flow graph generation and bytecode assembly."""
 
+import os
 from rpython.rlib import rfloat
 from rpython.rlib.objectmodel import we_are_translated
 
@@ -9,6 +10,10 @@
 from pypy.tool import stdlib_opcode as ops
 
 
+class StackDepthComputationError(Exception):
+    pass
+
+
 class Instruction(object):
     """Represents a single opcode."""
 
@@ -55,11 +60,13 @@
     reaches the end of the block, it continues to next_block.
     """
 
+    marked = False
+    have_return = False
+    auto_inserted_return = False
+
     def __init__(self):
         self.instructions = []
         self.next_block = None
-        self.marked = False
-        self.have_return = False
 
     def _post_order_see(self, stack, nextblock):
         if nextblock.marked == 0:
@@ -384,7 +391,11 @@
         # look into a block when all the previous blocks have been done.
         self._max_depth = 0
         for block in blocks:
-            self._do_stack_depth_walk(block)
+            depth = self._do_stack_depth_walk(block)
+            if block.auto_inserted_return and depth != 0:
+                os.write(2, "StackDepthComputationError in %s at %s:%s\n" % (
+                    self.compile_info.filename, self.name, self.first_lineno))
+                raise StackDepthComputationError   # fatal error
         return self._max_depth
 
     def _next_stack_depth_walk(self, nextblock, depth):
@@ -393,20 +404,21 @@
 
     def _do_stack_depth_walk(self, block):
         depth = block.initial_depth
-        done = False
         for instr in block.instructions:
             depth += _opcode_stack_effect(instr.opcode, instr.arg)
             if depth >= self._max_depth:
                 self._max_depth = depth
+            jump_op = instr.opcode
             if instr.has_jump:
                 target_depth = depth
-                jump_op = instr.opcode
                 if jump_op == ops.FOR_ITER:
                     target_depth -= 2
                 elif (jump_op == ops.SETUP_FINALLY or
                       jump_op == ops.SETUP_EXCEPT or
                       jump_op == ops.SETUP_WITH):
-                    target_depth += 3
+                    if jump_op == ops.SETUP_WITH:
+                        target_depth -= 1     # ignore the w_result just pushed
+                    target_depth += 3         # add [exc_type, exc, unroller]
                     if target_depth > self._max_depth:
                         self._max_depth = target_depth
                 elif (jump_op == ops.JUMP_IF_TRUE_OR_POP or
@@ -415,10 +427,14 @@
                 self._next_stack_depth_walk(instr.jump[0], target_depth)
                 if jump_op == ops.JUMP_ABSOLUTE or jump_op == ops.JUMP_FORWARD:
                     # Nothing more can occur.
-                    done = True
                     break
-        if block.next_block and not done:
-            self._next_stack_depth_walk(block.next_block, depth)
+            elif jump_op == ops.RETURN_VALUE or jump_op == ops.RAISE_VARARGS:
+                # Nothing more can occur.
+                break
+        else:
+            if block.next_block:
+                self._next_stack_depth_walk(block.next_block, depth)
+        return depth
 
     def _build_lnotab(self, blocks):
         """Build the line number table for tracebacks and tracing."""
@@ -471,6 +487,7 @@
             if self.add_none_to_final_return:
                 self.load_const(self.space.w_None)
             self.emit_op(ops.RETURN_VALUE)
+            self.current_block.auto_inserted_return = True
         # Set the first lineno if it is not already explicitly set.
         if self.first_lineno == -1:
             if self.first_block.instructions:
@@ -563,10 +580,10 @@
     ops.INPLACE_OR: -1,
     ops.INPLACE_XOR: -1,
 
-    ops.SLICE+0: 1,
-    ops.SLICE+1: 0,
-    ops.SLICE+2: 0,
-    ops.SLICE+3: -1,
+    ops.SLICE+0: 0,
+    ops.SLICE+1: -1,
+    ops.SLICE+2: -1,
+    ops.SLICE+3: -2,
     ops.STORE_SLICE+0: -2,
     ops.STORE_SLICE+1: -3,
     ops.STORE_SLICE+2: -3,
@@ -576,7 +593,7 @@
     ops.DELETE_SLICE+2: -2,
     ops.DELETE_SLICE+3: -3,
 
-    ops.STORE_SUBSCR: -2,
+    ops.STORE_SUBSCR: -3,
     ops.DELETE_SUBSCR: -2,
 
     ops.GET_ITER: 0,
@@ -593,7 +610,9 @@
 
     ops.WITH_CLEANUP: -1,
     ops.POP_BLOCK: 0,
-    ops.END_FINALLY: -1,
+    ops.END_FINALLY: -3,     # assume always 3: we pretend that SETUP_FINALLY
+                             # pushes 3.  In truth, it would only push 1 and
+                             # the corresponding END_FINALLY only pops 1.
     ops.SETUP_WITH: 1,
     ops.SETUP_FINALLY: 0,
     ops.SETUP_EXCEPT: 0,
@@ -604,7 +623,6 @@
     ops.YIELD_VALUE: 0,
     ops.BUILD_CLASS: -2,
     ops.BUILD_MAP: 1,
-    ops.BUILD_SET: 1,
     ops.COMPARE_OP: -1,
 
     ops.LOOKUP_METHOD: 1,
@@ -659,6 +677,9 @@
 def _compute_BUILD_LIST(arg):
     return 1 - arg
 
+def _compute_BUILD_SET(arg):
+    return 1 - arg
+
 def _compute_MAKE_CLOSURE(arg):
     return -arg - 1
 
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -772,6 +772,60 @@
         code = compile_with_astcompiler(source, 'exec', self.space)
         assert code.co_stacksize == 2
 
+    def test_stackeffect_bug3(self):
+        source = """if 1:
+        try: pass
+        finally: pass
+        try: pass
+        finally: pass
+        try: pass
+        finally: pass
+        try: pass
+        finally: pass
+        try: pass
+        finally: pass
+        try: pass
+        finally: pass
+        """
+        code = compile_with_astcompiler(source, 'exec', self.space)
+        assert code.co_stacksize == 3
+
+    def test_stackeffect_bug4(self):
+        source = """if 1:
+        with a: pass
+        with a: pass
+        with a: pass
+        with a: pass
+        with a: pass
+        with a: pass
+        """
+        code = compile_with_astcompiler(source, 'exec', self.space)
+        assert code.co_stacksize == 4
+
+    def test_stackeffect_bug5(self):
+        source = """if 1:
+        a[:]; a[:]; a[:]; a[:]; a[:]; a[:]
+        a[1:]; a[1:]; a[1:]; a[1:]; a[1:]; a[1:]
+        a[:2]; a[:2]; a[:2]; a[:2]; a[:2]; a[:2]
+        a[1:2]; a[1:2]; a[1:2]; a[1:2]; a[1:2]; a[1:2]
+        """
+        code = compile_with_astcompiler(source, 'exec', self.space)
+        assert code.co_stacksize == 3
+
+    def test_stackeffect_bug6(self):
+        source = """if 1:
+        {1}; {1}; {1}; {1}; {1}; {1}; {1}
+        """
+        code = compile_with_astcompiler(source, 'exec', self.space)
+        assert code.co_stacksize == 1
+
+    def test_stackeffect_bug7(self):
+        source = '''def f():
+            for i in a:
+                return
+        '''
+        code = compile_with_astcompiler(source, 'exec', self.space)
+
     def test_lambda(self):
         yield self.st, "y = lambda x: x", "y(4)", 4
 
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -374,14 +374,11 @@
         return space.wrap(self.name)
 
     def fset_func_name(self, space, w_name):
-        try:
+        if space.isinstance_w(w_name, space.w_str):
             self.name = space.str_w(w_name)
-        except OperationError, e:
-            if e.match(space, space.w_TypeError):
-                raise OperationError(space.w_TypeError,
-                                     space.wrap("func_name must be set "
-                                                "to a string object"))
-            raise
+        else:
+            raise OperationError(space.w_TypeError,
+                space.wrap("__name__ must be set to a string object"))
 
     def fdel_func_doc(self, space):
         self.w_doc = space.w_None
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -107,6 +107,12 @@
             __name__ = "bar"
             assert f.__module__ == "foo"''' in {}
 
+    def test_set_name(self):
+        def f(): pass
+        f.__name__ = 'g'
+        assert f.func_name == 'g'
+        raises(TypeError, "f.__name__ = u'g'")
+
 
 class AppTestFunction:
     def test_simple_call(self):
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -11,6 +11,7 @@
 
 
 class defaultdict(dict):
+    __slots__ = ['default_factory']
 
     def __init__(self, *args, **kwds):
         if len(args) > 0:
@@ -20,7 +21,7 @@
                 raise TypeError("first argument must be callable")
         else:
             default_factory = None
-        self.default_factory = default_factory
+        defaultdict.default_factory.__set__(self, default_factory)
         super(defaultdict, self).__init__(*args, **kwds)
 
     def __missing__(self, key):
@@ -33,15 +34,15 @@
             return "defaultdict(...)"
         try:
             recurse.add(id(self))
-            return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+            return "defaultdict(%s, %s)" % (self.default_factory,
+                                            super(defaultdict, self).__repr__())
         finally:
             recurse.remove(id(self))
 
     def copy(self):
         return type(self)(self.default_factory, self)
 
-    def __copy__(self):
-        return self.copy()
+    __copy__ = copy
 
     def __reduce__(self):
         """
@@ -55,4 +56,5 @@
 
            This API is used by pickle.py and copy.py.
         """
-        return (type(self), (self.default_factory,), None, None, self.iteritems())
+        return (type(self), (self.default_factory,), None, None,
+                defaultdict.iteritems(self))
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -54,3 +54,25 @@
         assert len(d2) == 1
         assert d2[2] == 3
         assert d2[3] == 42
+
+    def test_no_dict(self):
+        import _collections
+        assert not hasattr(_collections.defaultdict(), '__dict__')
+
+    def test_no_setattr(self):
+        import _collections
+        class D(_collections.defaultdict):
+            def __setattr__(self, attr, name):
+                raise AssertionError
+        d = D(int)
+        assert d['5'] == 0
+        d['6'] += 3
+        assert d['6'] == 3
+
+    def test_default_factory(self):
+        import _collections
+        f = lambda: 42
+        d = _collections.defaultdict(f)
+        assert d.default_factory is f
+        d.default_factory = lambda: 43
+        assert d['5'] == 43
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -91,39 +91,39 @@
 @cpython_api([PyObject], lltype.Void)
 def PyDict_Clear(space, w_obj):
     """Empty an existing dictionary of all key-value pairs."""
-    space.call_method(w_obj, "clear")
+    space.call_method(space.w_dict, "clear", w_obj)
 
 @cpython_api([PyObject], PyObject)
 def PyDict_Copy(space, w_obj):
     """Return a new dictionary that contains the same key-value pairs as p.
     """
-    return space.call_method(w_obj, "copy")
+    return space.call_method(space.w_dict, "copy", w_obj)
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PyDict_Update(space, w_obj, w_other):
     """This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b) in
     Python.  Return 0 on success or -1 if an exception was raised.
     """
-    space.call_method(w_obj, "update", w_other)
+    space.call_method(space.w_dict, "update", w_obj, w_other)
     return 0
 
 @cpython_api([PyObject], PyObject)
 def PyDict_Keys(space, w_obj):
     """Return a PyListObject containing all the keys from the dictionary,
     as in the dictionary method dict.keys()."""
-    return space.call_method(w_obj, "keys")
+    return space.call_method(space.w_dict, "keys", w_obj)
 
 @cpython_api([PyObject], PyObject)
 def PyDict_Values(space, w_obj):
     """Return a PyListObject containing all the values from the
     dictionary p, as in the dictionary method dict.values()."""
-    return space.call_method(w_obj, "values")
+    return space.call_method(space.w_dict, "values", w_obj)
 
 @cpython_api([PyObject], PyObject)
 def PyDict_Items(space, w_obj):
     """Return a PyListObject containing all the items from the
     dictionary, as in the dictionary method dict.items()."""
-    return space.call_method(w_obj, "items")
+    return space.call_method(space.w_dict, "items", w_obj)
 
 @cpython_api([PyObject, Py_ssize_tP, PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDict_Next(space, w_dict, ppos, pkey, pvalue):
@@ -175,7 +175,7 @@
     # not complete.
 
     try:
-        w_iter = space.call_method(w_dict, "iteritems")
+        w_iter = space.call_method(space.w_dict, "iteritems", w_dict)
         pos = ppos[0]
         while pos:
             space.call_method(w_iter, "next")
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -65,7 +65,7 @@
     """Insert the item item into list list in front of index index.  Return
     0 if successful; return -1 and set an exception if unsuccessful.
     Analogous to list.insert(index, item)."""
-    space.call_method(w_list, "insert", space.wrap(index), w_item)
+    space.call_method(space.w_list, "insert", w_list, space.wrap(index), w_item)
     return 0
 
 @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
@@ -98,7 +98,7 @@
     failure.  This is equivalent to list.sort()."""
     if not isinstance(w_list, W_ListObject):
         PyErr_BadInternalCall(space)
-    space.call_method(w_list, "sort")
+    space.call_method(space.w_list, "sort", w_list)
     return 0
 
 @cpython_api([PyObject], rffi.INT_real, error=-1)
@@ -107,7 +107,7 @@
     failure.  This is the equivalent of list.reverse()."""
     if not isinstance(w_list, W_ListObject):
         PyErr_BadInternalCall(space)
-    space.call_method(w_list, "reverse")
+    space.call_method(space.w_list, "reverse", w_list)
     return 0
 
 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -36,7 +36,7 @@
     values of brand new frozensets before they are exposed to other code."""
     if not PySet_Check(space, w_s):
         PyErr_BadInternalCall(space)
-    space.call_method(w_s, 'add', w_obj)
+    space.call_method(space.w_set, 'add', w_s, w_obj)
     return 0
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
@@ -49,7 +49,7 @@
     instance of set or its subtype."""
     if not PySet_Check(space, w_s):
         PyErr_BadInternalCall(space)
-    space.call_method(w_s, 'discard', w_obj)
+    space.call_method(space.w_set, 'discard', w_s, w_obj)
     return 0
 
 
@@ -59,12 +59,12 @@
     object from the set.  Return NULL on failure.  Raise KeyError if the
     set is empty. Raise a SystemError if set is an not an instance of
     set or its subtype."""
-    return space.call_method(w_set, "pop")
+    return space.call_method(space.w_set, "pop", w_set)
 
 @cpython_api([PyObject], rffi.INT_real, error=-1)
 def PySet_Clear(space, w_set):
     """Empty an existing set of all elements."""
-    space.call_method(w_set, 'clear')
+    space.call_method(space.w_set, 'clear', w_set)
     return 0
 
 @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
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
@@ -30,6 +30,9 @@
     for c in ['MAXDIMS', 'CLIP', 'WRAP', 'RAISE']:
         interpleveldefs[c] = 'space.wrap(constants.%s)' % c
 
+    def startup(self, space):
+        from pypy.module.micronumpy.concrete import _setup
+        _setup()
 
 class UMathModule(MixedModule):
     appleveldefs = {}
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -34,11 +34,13 @@
 
     @staticmethod
     def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True):
-        from pypy.module.micronumpy import concrete
+        from pypy.module.micronumpy import concrete, descriptor, boxes
         from pypy.module.micronumpy.strides import calc_strides
         strides, backstrides = calc_strides(shape, dtype.base, order)
         impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
                                       backstrides, zero=zero)
+        if dtype == descriptor.get_dtype_cache(space).w_objectdtype:
+            impl.fill(space, boxes.W_ObjectBox(space.w_None))
         if w_instance:
             return wrap_impl(space, space.type(w_instance), w_instance, impl)
         return W_NDimArray(impl)
@@ -123,7 +125,7 @@
     def get_shape(self):
         return self.implementation.get_shape()
 
-    def get_dtype(self):
+    def get_dtype(self, space=None):
         return self.implementation.dtype
 
     def get_order(self):
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -607,6 +607,19 @@
         #    arr.storage[i] = arg[i]
         return W_UnicodeBox(arr, 0, arr.dtype)
 
+class W_ObjectBox(W_GenericBox):
+    descr__new__, _get_dtype, descr_reduce = new_dtype_getter(NPY.OBJECT)
+
+    def __init__(self, w_obj):
+        self.w_obj = w_obj
+
+    def convert_to(self, space, dtype):
+        if dtype.is_bool():
+            return W_BoolBox(space.bool_w(self.w_obj))
+        return self # XXX
+
+    def descr__getattr__(self, space, w_key):
+        return space.getattr(self.w_obj, w_key)
 
 W_GenericBox.typedef = TypeDef("numpy.generic",
     __new__ = interp2app(W_GenericBox.descr__new__.im_func),
@@ -856,3 +869,9 @@
     __new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func),
     __len__ = interp2app(W_UnicodeBox.descr_len),
 )
+
+W_ObjectBox.typedef = TypeDef("numpy.object_", W_ObjectBox.typedef,
+    __new__ = interp2app(W_ObjectBox.descr__new__.im_func),
+    __getattr__ = interp2app(W_ObjectBox.descr__getattr__),
+)
+
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,7 +3,7 @@
 """
 import re
 from pypy.interpreter import special
-from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
+from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root, ObjSpace
 from pypy.interpreter.error import OperationError
 from rpython.rlib.objectmodel import specialize, instantiate
 from rpython.rlib.nonconst import NonConstant
@@ -47,7 +47,7 @@
     def lookup(self, name):
         return self.getdictvalue(self, name)
 
-class FakeSpace(object):
+class FakeSpace(ObjSpace):
     w_ValueError = W_TypeObject("ValueError")
     w_TypeError = W_TypeObject("TypeError")
     w_IndexError = W_TypeObject("IndexError")
@@ -67,6 +67,7 @@
     w_unicode = W_TypeObject("unicode")
     w_complex = W_TypeObject("complex")
     w_dict = W_TypeObject("dict")
+    w_object = W_TypeObject("object")
 
     def __init__(self):
         """NOT_RPYTHON"""
@@ -88,7 +89,8 @@
         return self.wrap(len(w_obj.items))
 
     def getattr(self, w_obj, w_attr):
-        return StringObject(NonConstant('foo'))
+        assert isinstance(w_attr, StringObject)
+        return w_obj.getdictvalue(self, w_attr.v)
 
     def isinstance_w(self, w_obj, w_tp):
         try:
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -1,11 +1,11 @@
 from pypy.interpreter.error import OperationError, oefmt
-from rpython.rlib import jit
+from rpython.rlib import jit, rgc
 from rpython.rlib.buffer import Buffer
-from rpython.rlib.debug import make_sure_not_resized
+from rpython.rlib.debug import make_sure_not_resized, debug_print
 from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \
     raw_storage_getitem, raw_storage_setitem, RAW_STORAGE
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.micronumpy import support, loop
+from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
+from pypy.module.micronumpy import support, loop, constants as NPY
 from pypy.module.micronumpy.base import convert_to_array, W_NDimArray, \
     ArrayArgumentException
 from pypy.module.micronumpy.iterators import ArrayIter
@@ -13,11 +13,13 @@
     RecordChunk, calc_strides, calc_new_strides, shape_agreement,
     calculate_broadcast_strides, calc_backstrides)
 from rpython.rlib.objectmodel import keepalive_until_here
+from rpython.rtyper.annlowlevel import cast_gcref_to_instance
+from pypy.interpreter.baseobjspace import W_Root
 
 
 class BaseConcreteArray(object):
     _immutable_fields_ = ['dtype?', 'storage', 'start', 'size', 'shape[*]',
-                          'strides[*]', 'backstrides[*]', 'order']
+                          'strides[*]', 'backstrides[*]', 'order', 'gcstruct']
     start = 0
     parent = None
     flags = 0
@@ -326,13 +328,54 @@
         return ArrayBuffer(self, readonly)
 
     def astype(self, space, dtype):
-        strides, backstrides = calc_strides(self.get_shape(), dtype,
-                                                    self.order)
+        # we want to create a new array, but must respect the strides
+        # in self. So find a factor of the itemtype.elsize, and use this
+        factor = float(dtype.elsize) / self.dtype.elsize
+        strides = [int(factor*s) for s in self.get_strides()]
+        backstrides = [int(factor*s) for s in self.get_backstrides()]
         impl = ConcreteArray(self.get_shape(), dtype, self.order,
                              strides, backstrides)
         loop.setslice(space, impl.get_shape(), impl, self)
         return impl
 
+OBJECTSTORE = lltype.GcStruct('ObjectStore',
+                              ('length', lltype.Signed),
+                              ('step', lltype.Signed),
+                              ('storage', llmemory.Address),
+                              rtti=True)
+offset_of_storage = llmemory.offsetof(OBJECTSTORE, 'storage')
+offset_of_length = llmemory.offsetof(OBJECTSTORE, 'length')
+offset_of_step = llmemory.offsetof(OBJECTSTORE, 'step')
+
+V_OBJECTSTORE = lltype.nullptr(OBJECTSTORE)
+
+def customtrace(gc, obj, callback, arg):
+    #debug_print('in customtrace w/obj', obj)
+    length = (obj + offset_of_length).signed[0]
+    step = (obj + offset_of_step).signed[0]
+    storage = (obj + offset_of_storage).address[0]
+    #debug_print('tracing', length, 'objects in ndarray.storage')
+    i = 0
+    while i < length:
+        gc._trace_callback(callback, arg, storage)
+        storage += step
+        i += 1
+    
+lambda_customtrace = lambda: customtrace
+
+def _setup():
+    rgc.register_custom_trace_hook(OBJECTSTORE, lambda_customtrace)
+
+ at jit.dont_look_inside
+def _create_objectstore(storage, length, elsize):
+    gcstruct = lltype.malloc(OBJECTSTORE)
+    # JIT does not support cast_ptr_to_adr
+    gcstruct.storage = llmemory.cast_ptr_to_adr(storage)
+    #print 'create gcstruct',gcstruct,'with storage',storage,'as',gcstruct.storage
+    gcstruct.length = length
+    gcstruct.step = elsize
+    return gcstruct
+
 
 class ConcreteArrayNotOwning(BaseConcreteArray):
     def __init__(self, shape, dtype, order, strides, backstrides, storage, start=0):
@@ -347,10 +390,11 @@
         self.backstrides = backstrides
         self.storage = storage
         self.start = start
+        self.gcstruct = V_OBJECTSTORE
 
     def fill(self, space, box):
         self.dtype.itemtype.fill(self.storage, self.dtype.elsize,
-                                 box, 0, self.size, 0)
+                                 box, 0, self.size, 0, self.gcstruct)
 
     def set_shape(self, space, orig_array, new_shape):
         strides, backstrides = calc_strides(new_shape, self.dtype,
@@ -374,17 +418,24 @@
     def base(self):
         return None
 
-
 class ConcreteArray(ConcreteArrayNotOwning):
     def __init__(self, shape, dtype, order, strides, backstrides,
                  storage=lltype.nullptr(RAW_STORAGE), zero=True):
+        gcstruct = V_OBJECTSTORE
         if storage == lltype.nullptr(RAW_STORAGE):
-            storage = dtype.itemtype.malloc(support.product(shape) *
-                                            dtype.elsize, zero=zero)
+            length = support.product(shape) 
+            if dtype.num == NPY.OBJECT:
+                storage = dtype.itemtype.malloc(length * dtype.elsize, zero=True)
+                gcstruct = _create_objectstore(storage, length, dtype.elsize)
+            else:
+                storage = dtype.itemtype.malloc(length * dtype.elsize, zero=zero)
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
                                         storage)
+        self.gcstruct = gcstruct
 
     def __del__(self):
+        if self.gcstruct:
+            self.gcstruct.length = 0
         free_raw_storage(self.storage, track_allocation=False)
 
 
@@ -423,6 +474,7 @@
             parent = parent.parent # one level only
         self.parent = parent
         self.storage = parent.storage
+        self.gcstruct = parent.gcstruct
         self.order = parent.order
         self.dtype = dtype
         self.size = support.product(shape) * self.dtype.elsize
@@ -480,6 +532,7 @@
 class VoidBoxStorage(BaseConcreteArray):
     def __init__(self, size, dtype):
         self.storage = alloc_raw_storage(size)
+        self.gcstruct = V_OBJECTSTORE
         self.dtype = dtype
         self.size = size
 
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -38,6 +38,34 @@
         raise oefmt(space.w_ValueError,
                     "object __array__ method not producing an array")
 
+def try_interface_method(space, w_object):
+    try:
+        w_interface = space.getattr(w_object, space.wrap("__array_interface__"))
+    except OperationError, e:
+        if e.match(space, space.w_AttributeError):
+            return None
+        raise
+    if w_interface is None:
+        # happens from compile.py
+        return None
+    version = space.int_w(space.finditem(w_interface, space.wrap("version")))
+    if version < 3:
+        raise oefmt(space.w_NotImplementedError,
+                "__array_interface__ version %d not supported", version)
+    # make a view into the data
+    w_shape = space.finditem(w_interface, space.wrap('shape'))
+    w_dtype = space.finditem(w_interface, space.wrap('typestr'))
+    w_descr = space.finditem(w_interface, space.wrap('descr'))
+    data_w = space.listview(space.finditem(w_interface, space.wrap('data')))
+    w_strides = space.finditem(w_interface, space.wrap('strides'))
+    shape = [space.int_w(i) for i in space.listview(w_shape)]
+    dtype = descriptor.decode_w_dtype(space, w_dtype)
+    rw = space.is_true(data_w[1])
+    #print 'create view from shape',shape,'dtype',dtype,'descr',w_descr,'data',data_w[0],'rw',rw
+    raise oefmt(space.w_NotImplementedError,
+                "creating array from __array_interface__ not supported yet")
+    return 
+    
 
 @unwrap_spec(ndmin=int, copy=bool, subok=bool)
 def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False,
@@ -63,7 +91,11 @@
             # continue with w_array, but do further operations in place
             w_object = w_array
             copy = False
-
+    if not isinstance(w_object, W_NDimArray):
+        w_array = try_interface_method(space, w_object)
+        if w_array is not None:
+            w_object = w_array
+            copy = False
     dtype = descriptor.decode_w_dtype(space, w_dtype)
 
     if space.is_none(w_order):
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -6,7 +6,7 @@
 from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
                                       interp_attrproperty, interp_attrproperty_w)
 from rpython.rlib import jit
-from rpython.rlib.objectmodel import specialize, compute_hash
+from rpython.rlib.objectmodel import specialize, compute_hash, we_are_translated
 from rpython.rlib.rarithmetic import r_longlong, r_ulonglong
 from pypy.module.micronumpy import types, boxes, base, support, constants as NPY
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
@@ -56,7 +56,7 @@
         self.char = char
         self.w_box_type = w_box_type
         if byteorder is None:
-            if itemtype.get_element_size() == 1:
+            if itemtype.get_element_size() == 1 or isinstance(itemtype, types.ObjectType):
                 byteorder = NPY.IGNORE
             else:
                 byteorder = NPY.NATIVE
@@ -112,6 +112,9 @@
     def is_str(self):
         return self.num == NPY.STRING
 
+    def is_object(self):
+        return self.num == NPY.OBJECT
+
     def is_str_or_unicode(self):
         return self.num == NPY.STRING or self.num == NPY.UNICODE
 
@@ -428,7 +431,7 @@
 
                 self.names.append(name)
                 self.fields[name] = offset, dtype
-            self.itemtype = types.RecordType()
+            self.itemtype = types.RecordType(space)
 
         if self.is_flexible():
             self.elsize = size
@@ -443,7 +446,7 @@
                 endian = NPY.OPPBYTE if self.is_native() else NPY.NATBYTE
             elif newendian != NPY.IGNORE:
                 endian = newendian
-        itemtype = self.itemtype.__class__(endian in (NPY.NATIVE, NPY.NATBYTE))
+        itemtype = self.itemtype.__class__(space, endian in (NPY.NATIVE, NPY.NATBYTE))
         fields = self.fields
         if fields is None:
             fields = {}
@@ -482,7 +485,7 @@
         fields[fldname] = (offset, subdtype)
         offset += subdtype.elsize
         names.append(fldname)
-    return W_Dtype(types.RecordType(), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
+    return W_Dtype(types.RecordType(space), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
                    space.gettypefor(boxes.W_VoidBox),
                    names=names, fields=fields, elsize=offset)
 
@@ -493,8 +496,17 @@
 
 
 def dtype_from_spec(space, w_spec):
-    w_lst = get_appbridge_cache(space).call_method(space,
-        'numpy.core._internal', '_commastring', Arguments(space, [w_spec]))
+
+    if we_are_translated():
+        w_lst = get_appbridge_cache(space).call_method(space,
+            'numpy.core._internal', '_commastring', Arguments(space, [w_spec]))
+    else:
+        # testing, handle manually
+        if space.eq_w(w_spec, space.wrap('u4,u4,u4')):
+            w_lst = space.newlist([space.wrap('u4')]*3)
+        else:
+            raise oefmt(space.w_RuntimeError,
+                    "cannot parse w_spec")
     if not space.isinstance_w(w_lst, space.w_list) or space.len_w(w_lst) < 1:
         raise oefmt(space.w_RuntimeError,
                     "_commastring is not returning a list with len >= 1")
@@ -541,15 +553,17 @@
         if size == 1:
             return subdtype
         size *= subdtype.elsize
-        return W_Dtype(types.VoidType(), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
+        return W_Dtype(types.VoidType(space), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
                        space.gettypefor(boxes.W_VoidBox),
                        shape=shape, subdtype=subdtype, elsize=size)
 
     if space.is_none(w_dtype):
         return cache.w_float64dtype
-    elif space.isinstance_w(w_dtype, w_subtype):
+    if space.isinstance_w(w_dtype, w_subtype):
         return w_dtype
-    elif space.isinstance_w(w_dtype, space.w_str):
+    if space.isinstance_w(w_dtype, space.w_unicode):
+        w_dtype = space.wrap(space.str_w(w_dtype))  # may raise if invalid
+    if space.isinstance_w(w_dtype, space.w_str):
         name = space.str_w(w_dtype)
         if _check_for_commastring(name):
             return dtype_from_spec(space, w_dtype)
@@ -585,8 +599,7 @@
         if w_dtype is dtype.w_box_type:
             return dtype
     if space.isinstance_w(w_dtype, space.w_type):
-        raise oefmt(space.w_NotImplementedError,
-            "cannot create dtype with type '%N'", w_dtype)
+        return cache.w_objectdtype
     raise oefmt(space.w_TypeError, "data type not understood")
 
 
@@ -653,7 +666,7 @@
 
 def new_string_dtype(space, size, char=NPY.STRINGLTR):
     return W_Dtype(
-        types.StringType(),
+        types.StringType(space),
         elsize=size,
         num=NPY.STRING,
         kind=NPY.STRINGLTR,
@@ -663,7 +676,7 @@
 
 
 def new_unicode_dtype(space, size):
-    itemtype = types.UnicodeType()
+    itemtype = types.UnicodeType(space)
     return W_Dtype(
         itemtype,
         elsize=size * itemtype.get_element_size(),
@@ -676,7 +689,7 @@
 
 def new_void_dtype(space, size):
     return W_Dtype(
-        types.VoidType(),
+        types.VoidType(space),
         elsize=size,
         num=NPY.VOID,
         kind=NPY.VOIDLTR,
@@ -688,126 +701,126 @@
 class DtypeCache(object):
     def __init__(self, space):
         self.w_booldtype = W_Dtype(
-            types.Bool(),
+            types.Bool(space),
             num=NPY.BOOL,
             kind=NPY.GENBOOLLTR,
             char=NPY.BOOLLTR,
             w_box_type=space.gettypefor(boxes.W_BoolBox),
         )
         self.w_int8dtype = W_Dtype(
-            types.Int8(),
+            types.Int8(space),
             num=NPY.BYTE,
             kind=NPY.SIGNEDLTR,
             char=NPY.BYTELTR,
             w_box_type=space.gettypefor(boxes.W_Int8Box),
         )
         self.w_uint8dtype = W_Dtype(
-            types.UInt8(),
+            types.UInt8(space),
             num=NPY.UBYTE,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.UBYTELTR,
             w_box_type=space.gettypefor(boxes.W_UInt8Box),
         )
         self.w_int16dtype = W_Dtype(
-            types.Int16(),
+            types.Int16(space),
             num=NPY.SHORT,
             kind=NPY.SIGNEDLTR,
             char=NPY.SHORTLTR,
             w_box_type=space.gettypefor(boxes.W_Int16Box),
         )
         self.w_uint16dtype = W_Dtype(
-            types.UInt16(),
+            types.UInt16(space),
             num=NPY.USHORT,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.USHORTLTR,
             w_box_type=space.gettypefor(boxes.W_UInt16Box),
         )
         self.w_int32dtype = W_Dtype(
-            types.Int32(),
+            types.Int32(space),
             num=NPY.INT,
             kind=NPY.SIGNEDLTR,
             char=NPY.INTLTR,
             w_box_type=space.gettypefor(boxes.W_Int32Box),
         )
         self.w_uint32dtype = W_Dtype(
-            types.UInt32(),
+            types.UInt32(space),
             num=NPY.UINT,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.UINTLTR,
             w_box_type=space.gettypefor(boxes.W_UInt32Box),
         )
         self.w_longdtype = W_Dtype(
-            types.Long(),
+            types.Long(space),
             num=NPY.LONG,
             kind=NPY.SIGNEDLTR,
             char=NPY.LONGLTR,
             w_box_type=space.gettypefor(boxes.W_LongBox),
         )
         self.w_ulongdtype = W_Dtype(
-            types.ULong(),
+            types.ULong(space),
             num=NPY.ULONG,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.ULONGLTR,
             w_box_type=space.gettypefor(boxes.W_ULongBox),
         )
         self.w_int64dtype = W_Dtype(
-            types.Int64(),
+            types.Int64(space),
             num=NPY.LONGLONG,
             kind=NPY.SIGNEDLTR,
             char=NPY.LONGLONGLTR,
             w_box_type=space.gettypefor(boxes.W_Int64Box),
         )
         self.w_uint64dtype = W_Dtype(
-            types.UInt64(),
+            types.UInt64(space),
             num=NPY.ULONGLONG,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.ULONGLONGLTR,
             w_box_type=space.gettypefor(boxes.W_UInt64Box),
         )
         self.w_float32dtype = W_Dtype(
-            types.Float32(),
+            types.Float32(space),
             num=NPY.FLOAT,
             kind=NPY.FLOATINGLTR,
             char=NPY.FLOATLTR,
             w_box_type=space.gettypefor(boxes.W_Float32Box),
         )
         self.w_float64dtype = W_Dtype(
-            types.Float64(),
+            types.Float64(space),
             num=NPY.DOUBLE,
             kind=NPY.FLOATINGLTR,
             char=NPY.DOUBLELTR,
             w_box_type=space.gettypefor(boxes.W_Float64Box),
         )
         self.w_floatlongdtype = W_Dtype(
-            types.FloatLong(),
+            types.FloatLong(space),
             num=NPY.LONGDOUBLE,
             kind=NPY.FLOATINGLTR,
             char=NPY.LONGDOUBLELTR,
             w_box_type=space.gettypefor(boxes.W_FloatLongBox),
         )
         self.w_complex64dtype = W_Dtype(
-            types.Complex64(),
+            types.Complex64(space),
             num=NPY.CFLOAT,
             kind=NPY.COMPLEXLTR,
             char=NPY.CFLOATLTR,
             w_box_type=space.gettypefor(boxes.W_Complex64Box),
         )
         self.w_complex128dtype = W_Dtype(
-            types.Complex128(),
+            types.Complex128(space),
             num=NPY.CDOUBLE,
             kind=NPY.COMPLEXLTR,
             char=NPY.CDOUBLELTR,
             w_box_type=space.gettypefor(boxes.W_Complex128Box),
         )
         self.w_complexlongdtype = W_Dtype(
-            types.ComplexLong(),
+            types.ComplexLong(space),
             num=NPY.CLONGDOUBLE,
             kind=NPY.COMPLEXLTR,
             char=NPY.CLONGDOUBLELTR,
             w_box_type=space.gettypefor(boxes.W_ComplexLongBox),
         )
         self.w_stringdtype = W_Dtype(
-            types.StringType(),
+            types.StringType(space),
             elsize=0,
             num=NPY.STRING,
             kind=NPY.STRINGLTR,
@@ -815,7 +828,7 @@
             w_box_type=space.gettypefor(boxes.W_StringBox),
         )
         self.w_unicodedtype = W_Dtype(
-            types.UnicodeType(),
+            types.UnicodeType(space),
             elsize=0,
             num=NPY.UNICODE,
             kind=NPY.UNICODELTR,
@@ -823,7 +836,7 @@
             w_box_type=space.gettypefor(boxes.W_UnicodeBox),
         )
         self.w_voiddtype = W_Dtype(
-            types.VoidType(),
+            types.VoidType(space),
             elsize=0,
             num=NPY.VOID,
             kind=NPY.VOIDLTR,
@@ -831,26 +844,33 @@
             w_box_type=space.gettypefor(boxes.W_VoidBox),
         )
         self.w_float16dtype = W_Dtype(
-            types.Float16(),
+            types.Float16(space),
             num=NPY.HALF,
             kind=NPY.FLOATINGLTR,
             char=NPY.HALFLTR,
             w_box_type=space.gettypefor(boxes.W_Float16Box),
         )
         self.w_intpdtype = W_Dtype(
-            types.Long(),
+            types.Long(space),
             num=NPY.LONG,
             kind=NPY.SIGNEDLTR,
             char=NPY.INTPLTR,
             w_box_type=space.gettypefor(boxes.W_LongBox),
         )
         self.w_uintpdtype = W_Dtype(
-            types.ULong(),
+            types.ULong(space),
             num=NPY.ULONG,
             kind=NPY.UNSIGNEDLTR,
             char=NPY.UINTPLTR,
             w_box_type=space.gettypefor(boxes.W_ULongBox),
         )
+        self.w_objectdtype = W_Dtype(
+            types.ObjectType(space),
+            num=NPY.OBJECT,
+            kind=NPY.OBJECTLTR,
+            char=NPY.OBJECTLTR,
+            w_box_type=space.gettypefor(boxes.W_ObjectBox),
+        )
         aliases = {
             NPY.BOOL:        ['bool_', 'bool8'],
             NPY.BYTE:        ['byte'],
@@ -869,6 +889,7 @@
             NPY.CLONGDOUBLE: ['clongdouble', 'clongfloat'],
             NPY.STRING:      ['string_', 'str'],
             NPY.UNICODE:     ['unicode_'],
+            NPY.OBJECT:      ['object_'],
         }
         self.alternate_constructors = {
             NPY.BOOL:     [space.w_bool],
@@ -887,6 +908,8 @@
             NPY.UNICODE:  [space.w_unicode],
             NPY.VOID:     [space.gettypefor(boxes.W_GenericBox)],
                            #space.w_buffer,  # XXX no buffer in space
+            NPY.OBJECT:   [space.gettypefor(boxes.W_ObjectBox),
+                           space.w_object],
         }
         float_dtypes = [self.w_float16dtype, self.w_float32dtype,
                         self.w_float64dtype, self.w_floatlongdtype]
@@ -906,7 +929,7 @@
             self.w_int64dtype, self.w_uint64dtype,
             ] + float_dtypes + complex_dtypes + [
             self.w_stringdtype, self.w_unicodedtype, self.w_voiddtype,
-            self.w_intpdtype, self.w_uintpdtype,
+            self.w_intpdtype, self.w_uintpdtype, self.w_objectdtype,
         ]
         self.float_dtypes_by_num_bytes = sorted(
             (dtype.elsize, dtype)
@@ -958,6 +981,7 @@
             'USHORT': self.w_uint16dtype,
             'FLOAT': self.w_float32dtype,
             'BOOL': self.w_booldtype,
+            'OBJECT': self.w_objectdtype,
         }
 
         typeinfo_partial = {
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -202,11 +202,16 @@
             return self
         elif isinstance(w_idx, W_NDimArray) and w_idx.get_dtype().is_bool() \
                 and w_idx.ndims() > 0:
-            return self.getitem_filter(space, w_idx)
-        try:
-            return self.implementation.descr_getitem(space, self, w_idx)
-        except ArrayArgumentException:
-            return self.getitem_array_int(space, w_idx)
+            w_ret = self.getitem_filter(space, w_idx)
+        else:
+            try:
+                w_ret = self.implementation.descr_getitem(space, self, w_idx)
+            except ArrayArgumentException:
+                w_ret = self.getitem_array_int(space, w_idx)
+        if isinstance(w_ret, boxes.W_ObjectBox):
+            #return the W_Root object, not a scalar
+            w_ret = w_ret.w_obj
+        return w_ret
 
     def getitem(self, space, index_list):
         return self.implementation.getitem_index(space, index_list)
@@ -550,6 +555,7 @@
             else:
                 strides = self.descr_get_strides(space)
             space.setitem_str(w_d, 'strides', strides)
+            space.setitem_str(w_d, 'version', space.wrap(3))
             return w_d
 
     w_pypy_data = None
@@ -845,7 +851,7 @@
                         "new type not compatible with array."))
                 # Strides, shape does not change
                 v = impl.astype(space, dtype)
-                return wrap_impl(space, w_type, self, v) 
+                return wrap_impl(space, w_type, self, v)
             strides = impl.get_strides()
             if dims == 1 or strides[0] <strides[-1]:
                 # Column-major, resize first dimension
@@ -1205,7 +1211,7 @@
                         "improper dtype '%R'", dtype)
         self.implementation = W_NDimArray.from_shape_and_storage(
             space, [space.int_w(i) for i in space.listview(shape)],
-            rffi.str2charp(space.str_w(storage), track_allocation=False), 
+            rffi.str2charp(space.str_w(storage), track_allocation=False),
             dtype, storage_bytes=space.len_w(storage), owning=True).implementation
 
     def descr___array_finalize__(self, space, w_obj):
diff --git a/pypy/module/micronumpy/test/dummy_module.py b/pypy/module/micronumpy/test/dummy_module.py
--- a/pypy/module/micronumpy/test/dummy_module.py
+++ b/pypy/module/micronumpy/test/dummy_module.py
@@ -20,7 +20,7 @@
 for t in types:
     globals()[t] = dtype(t).type
 
-types = ['bool', 'int', 'float', 'complex', 'str', 'string', 'unicode']
+types = ['bool', 'int', 'float', 'complex', 'str', 'string', 'unicode', 'object']
 for t in types:
     globals()[t + '_'] = dtype(t).type
 del types
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
@@ -58,6 +58,7 @@
         assert exc.value[0] == "there are no fields defined"
 
         assert dtype('int8').num == 1
+        assert dtype(u'int8').num == 1
         assert dtype('int8').name == 'int8'
         assert dtype('void').name == 'void'
         assert dtype(int).fields is None
@@ -472,11 +473,13 @@
         class O(object):
             pass
         for o in [object, O]:
-            if '__pypy__' not in sys.builtin_module_names:
+            print np.dtype(o).byteorder
+            if self.ptr_size == 4:
+                assert np.dtype(o).str == '|O4'
+            elif self.ptr_size == 8:
                 assert np.dtype(o).str == '|O8'
             else:
-                exc = raises(NotImplementedError, "np.dtype(o)")
-                assert exc.value[0] == "cannot create dtype with type '%s'" % o.__name__
+                assert False,'self._ptr_size unknown'
 
 class AppTestTypes(BaseAppTestDtypes):
     def test_abstract_types(self):
@@ -1348,15 +1351,4 @@
         assert a[0] == 1
         assert (a + a)[1] == 4
 
-class AppTestObjectDtypes(BaseNumpyAppTest):
-    def test_scalar_from_object(self):
-        from numpy import array
-        import sys
-        class Polynomial(object):
-            pass
-        if '__pypy__' in sys.builtin_module_names:
-            exc = raises(NotImplementedError, array, Polynomial())
-            assert exc.value.message.find('unable to create dtype from objects') >= 0
-        else:
-            a = array(Polynomial())
-            assert a.shape == ()
+
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -17,6 +17,7 @@
     def __init__(self):
         self.base = self
         self.elsize = 1
+        self.num = 0
 
 
 def create_slice(space, a, chunks):
@@ -2182,7 +2183,8 @@
         assert b.dtype == 'bool'
 
         a = arange(6, dtype='f4').reshape(2,3)
-        b = a.astype('i4')
+        b = a.T.astype('i4')
+        assert (a.T.strides == b.strides)
 
         a = array('x').astype('S3').dtype
         assert a.itemsize == 3
@@ -3150,11 +3152,7 @@
         assert b[35] == 200
         b[[slice(25, 30)]] = range(5)
         assert all(a[:5] == range(5))
-        import sys
-        if '__pypy__' not in sys.builtin_module_names:
-            raises(TypeError, 'b[[[slice(25, 125)]]]')
-        else:
-            raises(NotImplementedError, 'b[[[slice(25, 125)]]]')
+        raises(IndexError, 'b[[[slice(25, 125)]]]')
 
     def test_cumsum(self):
         from numpy import arange
diff --git a/pypy/module/micronumpy/test/test_object_arrays.py b/pypy/module/micronumpy/test/test_object_arrays.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_object_arrays.py
@@ -0,0 +1,162 @@
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestObjectDtypes(BaseNumpyAppTest):
+    def test_scalar_from_object(self):
+        from numpy import array
+        import sys
+        class Polynomial(object):
+            def whatami(self):
+                return 'an object'
+        a = array(Polynomial())
+        assert a.shape == ()
+        assert a.sum().whatami() == 'an object'
+
+    def test_uninitialized_object_array_is_filled_by_None(self):
+        import numpy as np
+
+        a = np.ndarray([5], dtype="O")
+
+        assert a[0] == None
+
+    def test_object_arrays_add(self):
+        import numpy as np
+
+        a = np.array(["foo"], dtype=object)
+        b = np.array(["bar"], dtype=object)
+        raises(TypeError, np.add, a, 1)
+        res = a + b
+        assert res[0] == "foobar"
+
+    def test_bool_func(self):
+        import numpy as np
+        a = np.array(["foo"], dtype=object)
+        b = a and complex(1, -1)
+        assert b == complex(1, -1)
+        b = np.array(complex(1, -1)) and a
+        assert (b == a).all()
+        c = np.array([1, 2, 3])
+        assert (a[0] != c[0])
+        assert (c[0] != a[0])
+        assert (a[0] > c[0])
+        assert (not a[0] < c[0])
+        assert (c[0] < a[0])
+        assert (not c[0] > a[0])
+
+    def test_logical_ufunc(self):
+        import numpy as np
+        import sys
+
+        if '__pypy__' in sys.builtin_module_names:
+            skip('need to refactor use of raw_xxx_op in types to make this work')
+        a = np.array(["foo"], dtype=object)
+        b = np.array([1], dtype=object)
+        d = np.array([complex(1, 10)], dtype=object)
+        c = np.logical_and(a, 1)
+        assert c.dtype == np.dtype('object')
+        assert c == 1
+        c = np.logical_and(b, complex(1, -1))
+        assert c.dtype == np.dtype('object')
+        assert c == complex(1, -1)
+        c = np.logical_and(d, b)
+        assert c == 1
+        c = b & 1
+        assert c.dtype == np.dtype('object')
+        assert (c == 1).all()
+        c = np.array(1) & b
+        assert (c == b).all()
+
+    def test_reduce(self):
+        import numpy as np
+        class O(object):
+            def whatami(self):
+                return 'an object'
+        fiveOs = [O()] * 5
+        a = np.array(fiveOs, dtype=object)
+        print np.maximum
+        b = np.maximum.reduce(a)
+        assert b is not None
+
+    def test_complex_op(self):
+        import numpy as np
+        import sys
+        a = np.array(['abc', 'def'], dtype=object) 
+        b = np.array([1, 2, 3], dtype=object) 
+        c = np.array([complex(1, 1), complex(1, -1)], dtype=object)
+        for arg in (a,b,c):
+            assert (arg == np.real(arg)).all()
+            assert (0 == np.imag(arg)).all()
+        if '__pypy__' in sys.builtin_module_names:
+            skip('not implemented yet')
+        raises(AttributeError, np.conj, a)
+        res = np.conj(b)
+        assert (res == b).all()
+        res = np.conj(c)
+        assert res[0] == c[1] and res[1] == c[0]
+
+    def test_keep_object_alive(self):
+        # only translated does it really test the gc
+        import numpy as np
+        import gc
+        class O(object):
+            def whatami(self):
+                return 'an object'
+        fiveOs = [O()] * 5
+        a = np.array(fiveOs, dtype=object)
+        del fiveOs
+        gc.collect()
+        assert a[2].whatami() == 'an object'
+
+    def test_array_interface(self):
+        import numpy as np
+        import sys
+        class DummyArray(object):
+            def __init__(self, interface, base=None):
+                self.__array_interface__ = interface
+                self.base = base
+        a = np.array([(1, 2, 3)], dtype='u4,u4,u4')
+        b = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='u4,u4,u4')
+        interface = dict(a.__array_interface__)
+        interface['shape'] = tuple([3])
+        interface['strides'] = tuple([0])
+        if '__pypy__' in sys.builtin_module_names:
+            skip('not implemented yet')
+        c = np.array(DummyArray(interface, base=a))
+        c.dtype = a.dtype
+        #print c
+        assert (c == np.array([(1, 2, 3), (1, 2, 3), (1, 2, 3)], dtype='u4,u4,u4') ).all()
+
+    def test_for_object_scalar_creation(self):
+        import numpy as np
+        import sys
+        a = np.object_()
+        b = np.object_(3)
+        b2 = np.object_(3.0)
+        c = np.object_([4, 5])
+        d = np.array([None])[0]
+        assert a is None
+        assert type(b) is int
+        assert type(b2) is float
+        assert type(c) is np.ndarray
+        assert c.dtype == object
+        assert type(d) is type(None)
+        if '__pypy__' in sys.builtin_module_names:
+            skip('not implemented yet')
+        e = np.object_([None, {}, []])
+        assert e.dtype == object
+
+    def test_mem_array_creation_invalid_specification(self):
+        # while not specifically testing object dtype, this
+        # test segfaulted during ObjectType.store due to
+        # missing gc hooks
+        import numpy as np
+        import sys
+        ytype = np.object_
+        if '__pypy__' in sys.builtin_module_names:
+            ytype = str
+        dt = np.dtype([('x', int), ('y', ytype)])
+        # Correct way
+        a = np.array([(1, 'object')], dt)
+        # Wrong way - should complain about writing buffer to object dtype
+        raises(ValueError, np.array, [1, 'object'], dt)
+
diff --git a/pypy/module/micronumpy/test/test_selection.py b/pypy/module/micronumpy/test/test_selection.py
--- a/pypy/module/micronumpy/test/test_selection.py
+++ b/pypy/module/micronumpy/test/test_selection.py
@@ -12,14 +12,11 @@
             exp = sorted(range(len(exp)), key=exp.__getitem__)
             c = a.copy()
             res = a.argsort()
-            assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
+            assert (res == exp).all(), 'Failed sortng %r\na=%r\nres=%r\nexp=%r' % (dtype,a,res,exp)
             assert (a == c).all() # not modified
 
             a = arange(100, dtype=dtype)
             assert (a.argsort() == a).all()
-        import sys
-        if '__pypy__' in sys.builtin_module_names:
-            raises(NotImplementedError, 'arange(10,dtype="float16").argsort()')
 
     def test_argsort_ndim(self):
         from numpy import array
@@ -63,14 +60,13 @@
                       'i2', complex]:
             a = array([6, 4, -1, 3, 8, 3, 256+20, 100, 101], dtype=dtype)
             exp = sorted(list(a))
-            res = a.copy()
-            res.sort()
-            assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
+            a.sort()
+            assert (a == exp).all(), 'Failed sorting %r\n%r\n%r' % (dtype, a, exp)
 
             a = arange(100, dtype=dtype)
             c = a.copy()
             a.sort()
-            assert (a == c).all()
+            assert (a == c).all(), 'Failed sortng %r\na=%r\nc=%r' % (dtype,a,c)
 
     def test_sort_nonnative(self):
         from numpy import array
@@ -222,6 +218,7 @@
 
     def test_sort_objects(self):
         # test object array sorts.
+        skip('object type not supported yet')
         from numpy import empty
         try:
             a = empty((101,), dtype=object)
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
@@ -397,11 +397,11 @@
         for i in range(3):
             assert min_c_b[i] == min(b[i], c)
 
-    def test_scalar(self):
+    def test_all_available(self):
         # tests that by calling all available ufuncs on scalars, none will
         # raise uncaught interp-level exceptions, (and crash the test)
         # and those that are uncallable can be accounted for.
-        # test on the four base-class dtypes: int, bool, float, complex
+        # test on the base-class dtypes: int, bool, float, complex, object
         # We need this test since they have no common base class.
         import numpy as np
         def find_uncallable_ufuncs(dtype):
@@ -412,6 +412,11 @@
                 if isinstance(u, np.ufunc):
                     try:
                         u(* [array] * u.nin)
+                    except AttributeError:
+                        pass
+                    except NotImplementedError:
+                        print s
+                        uncallable.add(s)
                     except TypeError:
                         assert s not in uncallable
                         uncallable.add(s)
@@ -427,6 +432,9 @@
                  'fabs', 'fmod', 'invert', 'mod',
                  'logaddexp', 'logaddexp2', 'left_shift', 'right_shift',
                  'copysign', 'signbit', 'ceil', 'floor', 'trunc'])
+        assert find_uncallable_ufuncs('object') == set(
+                ['isnan', 'logaddexp2', 'copysign', 'isfinite', 'signbit',
+                 'isinf', 'logaddexp'])
 
     def test_int_only(self):
         from numpy import bitwise_and, array
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
@@ -9,6 +9,7 @@
 from pypy.module.micronumpy.compile import FakeSpace, Parser, InterpreterState
 from pypy.module.micronumpy.base import W_NDimArray
 
+py.test.skip('move these to pypyjit/test_pypy_c/test_micronumpy')
 
 class TestNumpyJit(LLJitMixin):
     graph = None
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
@@ -3,8 +3,9 @@
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.objspace.std.floatobject import float2string
 from pypy.objspace.std.complexobject import str_format
+from pypy.interpreter.baseobjspace import W_Root, ObjSpace
 from rpython.rlib import clibffi, jit, rfloat, rcomplex
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib.rarithmetic import widen, byteswap, r_ulonglong, \
     most_neg_value_of, LONG_BIT
 from rpython.rlib.rawstorage import (alloc_raw_storage,
@@ -14,10 +15,12 @@
                                        pack_float80, unpack_float80)
 from rpython.rlib.rstruct.nativefmttable import native_is_bigendian
 from rpython.rlib.rstruct.runpack import runpack
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref,\
+     cast_gcref_to_instance
+from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
 from rpython.tool.sourcetools import func_with_new_name
 from pypy.module.micronumpy import boxes
-from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage
+from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage, V_OBJECTSTORE
 from pypy.module.micronumpy.strides import calc_strides
 
 degToRad = math.pi / 180.0
@@ -109,10 +112,12 @@
     return dispatcher
 
 class BaseType(object):
-    _immutable_fields_ = ['native']
+    _immutable_fields_ = ['native', 'space']
 
-    def __init__(self, native=True):
+    def __init__(self, space, native=True):
+        assert isinstance(space, ObjSpace)
         self.native = native
+        self.space = space
 
     def __repr__(self):
         return self.__class__.__name__
@@ -191,7 +196,7 @@
         with arr as storage:
             self._write(storage, i, offset, self.unbox(box))
 
-    def fill(self, storage, width, box, start, stop, offset):
+    def fill(self, storage, width, box, start, stop, offset, gcstruct):
         value = self.unbox(box)
         for i in xrange(start, stop, width):
             self._write(storage, i, offset, value)
@@ -306,7 +311,7 @@
 
     @raw_unary_op
     def rint(self, v):
-        float64 = Float64()
+        float64 = Float64(self.space)
         return float64.rint(float64.box(v))
 
 class Bool(BaseType, Primitive):
@@ -399,7 +404,7 @@
     def round(self, v, decimals=0):
         if decimals != 0:
             return v
-        return Float64().box(self.unbox(v))
+        return Float64(self.space).box(self.unbox(v))
 
 class Integer(Primitive):
     _mixin_ = True
@@ -444,7 +449,7 @@
                 self.T is rffi.LONG or self.T is rffi.LONGLONG):
             if v2 == -1 and v1 == self.for_computation(most_neg_value_of(self.T)):
                 return self.box(0)
-        return self.box(v1 // v2)
+        return self.box(v1 / v2)
 
     @simple_binary_op
     def mod(self, v1, v2):
@@ -1152,7 +1157,7 @@
         with arr as storage:
             self._write(storage, i, offset, self.unbox(box))
 
-    def fill(self, storage, width, box, start, stop, offset):
+    def fill(self, storage, width, box, start, stop, offset, gcstruct):
         value = self.unbox(box)
         for i in xrange(start, stop, width):
             self._write(storage, i, offset, value)
@@ -1253,25 +1258,25 @@
     def ge(self, v1, v2):
         return self._lt(v2, v1) or self._eq(v2, v1)
 
-    def _bool(self, v):
+    def _cbool(self, v):
         return bool(v[0]) or bool(v[1])
 
     @raw_binary_op
     def logical_and(self, v1, v2):
-        return self._bool(v1) and self._bool(v2)
+        return self._cbool(v1) and self._cbool(v2)
 
     @raw_binary_op
     def logical_or(self, v1, v2):
-        return self._bool(v1) or self._bool(v2)
+        return self._cbool(v1) or self._cbool(v2)
 
     @raw_unary_op
     def logical_not(self, v):
-        return not self._bool(v)
+        return not self._cbool(v)
 
     @raw_binary_op
     def logical_xor(self, v1, v2):
-        a = self._bool(v1)
-        b = self._bool(v2)
+        a = self._cbool(v1)
+        b = self._cbool(v2)
         return (not b and a) or (not a and b)
 
     def min(self, v1, v2):
@@ -1629,6 +1634,283 @@
         BoxType = boxes.W_ComplexLongBox
         ComponentBoxType = boxes.W_FloatLongBox
 
+_all_objs_for_tests = [] # for tests
+
+class ObjectType(Primitive, BaseType):
+    T = lltype.Signed
+    BoxType = boxes.W_ObjectBox
+
+    def get_element_size(self):
+        return rffi.sizeof(lltype.Signed)
+
+    def coerce(self, space, dtype, w_item):
+        if isinstance(w_item, boxes.W_ObjectBox):
+            return w_item
+        return boxes.W_ObjectBox(w_item)
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # return the item itself
+        return self.unbox(self.box(w_item))
+
+    def store(self, arr, i, offset, box):
+        if arr.gcstruct is V_OBJECTSTORE:
+            raise oefmt(self.space.w_NotImplementedError,
+                "cannot store object in array with no gc hook")
+        self._write(arr.storage, i, offset, self.unbox(box),
+                    arr.gcstruct)
+
+    def read(self, arr, i, offset, dtype=None):
+        return self.box(self._read(arr.storage, i, offset))
+
+    def byteswap(self, w_v):
+        return w_v
+
+    @jit.dont_look_inside
+    def _write(self, storage, i, offset, w_obj, gcstruct):
+        # no GC anywhere in this function!
+        if we_are_translated():
+            from rpython.rlib import rgc
+            rgc.ll_writebarrier(gcstruct)
+            value = rffi.cast(lltype.Signed, cast_instance_to_gcref(w_obj))
+        else:


More information about the pypy-commit mailing list