Author: Maciej Fijalkowski <[email protected]>
Branch: resume-refactor
Changeset: r66401:ea101e9bbee4
Date: 2013-08-28 15:04 +0100
http://bitbucket.org/pypy/pypy/changeset/ea101e9bbee4/

Log:    merge jitframe-offset

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
@@ -88,13 +88,27 @@
         w_res = W_NDimArray.from_shape(space, res_shape, self.get_dtype(), 
w_instance=self)
         return loop.getitem_filter(w_res, self, arr)
 
-    def setitem_filter(self, space, idx, val):
+    def setitem_filter(self, space, idx, value):
+        from pypy.module.micronumpy.interp_boxes import Box
+        val = value
         if len(idx.get_shape()) > 1 and idx.get_shape() != self.get_shape():
             raise OperationError(space.w_ValueError,
                                  space.wrap("boolean index array should have 1 
dimension"))
         if idx.get_size() > self.get_size():
             raise OperationError(space.w_ValueError,
                                  space.wrap("index out of range for array"))
+        idx_iter = idx.create_iter(self.get_shape())
+        size = loop.count_all_true_iter(idx_iter, self.get_shape(), 
idx.get_dtype())
+        if len(val.get_shape()) > 0 and val.get_shape()[0] > 1 and size > 
val.get_shape()[0]:
+            raise OperationError(space.w_ValueError, space.wrap("NumPy boolean 
array indexing assignment "
+                                                                "cannot assign 
%d input values to "
+                                                                "the %d output 
values where the mask is true" % (val.get_shape()[0],size)))
+        if val.get_shape() == [1]:
+            box = val.descr_getitem(space, space.wrap(0))
+            assert isinstance(box, Box)
+            val = W_NDimArray(scalar.Scalar(val.get_dtype(), box))
+        elif val.get_shape() == [0]:
+            val.implementation.dtype = self.implementation.dtype
         loop.setitem_filter(self, idx, val)
 
     def _prepare_array_index(self, space, w_index):
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -318,23 +318,27 @@
         lefti.next()
     return result
 
-count_all_true_driver = jit.JitDriver(name = 'numpy_count',
-                                      greens = ['shapelen', 'dtype'],
-                                      reds = 'auto')
 
 def count_all_true(arr):
-    s = 0
     if arr.is_scalar():
         return arr.get_dtype().itemtype.bool(arr.get_scalar_value())
     iter = arr.create_iter()
-    shapelen = len(arr.get_shape())
-    dtype = arr.get_dtype()
+    return count_all_true_iter(iter, arr.get_shape(), arr.get_dtype())
+
+count_all_true_iter_driver = jit.JitDriver(name = 'numpy_count',
+                                      greens = ['shapelen', 'dtype'],
+                                      reds = 'auto')
+def count_all_true_iter(iter, shape, dtype):
+    s = 0
+    shapelen = len(shape)
+    dtype = dtype
     while not iter.done():
-        count_all_true_driver.jit_merge_point(shapelen=shapelen, dtype=dtype)
+        count_all_true_iter_driver.jit_merge_point(shapelen=shapelen, 
dtype=dtype)
         s += iter.getitem_bool()
         iter.next()
     return s
 
+
 getitem_filter_driver = jit.JitDriver(name = 'numpy_getitem_bool',
                                       greens = ['shapelen', 'arr_dtype',
                                                 'index_dtype'],
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
@@ -2354,6 +2354,12 @@
     def test_array_indexing_bool_specialcases(self):
         from numpypy import arange, array
         a = arange(6)
+        try:
+            a[a < 3] = [1, 2]
+            assert False, "Should not work"
+        except ValueError:
+            pass
+        a = arange(6)
         a[a > 3] = array([15])
         assert (a == [0, 1, 2, 3, 15, 15]).all()
         a = arange(6).reshape(3, 2)
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -5,7 +5,7 @@
 from rpython.tool.ansi_print import ansi_log
 from rpython.tool.pairtype import pair
 from rpython.tool.error import (format_blocked_annotation_error,
-                             AnnotatorError, gather_error, ErrorWrapper)
+                             AnnotatorError, gather_error, ErrorWrapper, 
source_lines)
 from rpython.flowspace.model import (Variable, Constant, FunctionGraph,
                                       c_last_exception, checkgraph)
 from rpython.translator import simplify, transform
@@ -383,8 +383,8 @@
         try:
             unions = [annmodel.unionof(c1,c2) for c1, c2 in 
zip(oldcells,inputcells)]
         except annmodel.UnionError, e:
-            e.args = e.args + (
-                ErrorWrapper(gather_error(self, graph, block, None)),)
+            # Add source code to the UnionError
+            e.source = '\n'.join(source_lines(graph, block, None, long=True))
             raise
         # if the merged cells changed, we must redo the analysis
         if unions != oldcells:
diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -243,14 +243,16 @@
 
             if t2 is int:
                 if int2.nonneg == False:
-                    raise UnionError, "Merging %s and a possibly negative int 
is not allowed" % t1
+                    raise UnionError(int1, int2, "RPython cannot prove that 
these " + \
+                            "integers are of the same signedness")
                 knowntype = t1
             elif t1 is int:
                 if int1.nonneg == False:
-                    raise UnionError, "Merging %s and a possibly negative int 
is not allowed" % t2
+                    raise UnionError(int1, int2, "RPython cannot prove that 
these " + \
+                            "integers are of the same signedness")
                 knowntype = t2
             else:
-                raise UnionError, "Merging these types (%s, %s) is not 
supported" % (t1, t2)
+                raise UnionError(int1, int2)
         return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
                            knowntype=knowntype)
 
@@ -551,9 +553,9 @@
 
     def union((tup1, tup2)):
         if len(tup1.items) != len(tup2.items):
-            raise UnionError("cannot take the union of a tuple of length %d "
-                             "and a tuple of length %d" % (len(tup1.items),
-                                                           len(tup2.items)))
+            raise UnionError(tup1, tup2, "RPython cannot unify tuples of "
+                    "different length: %d versus %d" % \
+                    (len(tup1.items), len(tup2.items)))
         else:
             unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)]
             return SomeTuple(items = unions)
@@ -726,7 +728,8 @@
         else:
             basedef = ins1.classdef.commonbase(ins2.classdef)
             if basedef is None:
-                raise UnionError(ins1, ins2)
+                raise UnionError(ins1, ins2, "RPython cannot unify instances "
+                        "with no common base class")
         flags = ins1.flags
         if flags:
             flags = flags.copy()
@@ -768,7 +771,8 @@
     def union((iter1, iter2)):
         s_cont = unionof(iter1.s_container, iter2.s_container)
         if iter1.variant != iter2.variant:
-            raise UnionError("merging incompatible iterators variants")
+            raise UnionError(iter1, iter2,
+                    "RPython cannot unify incompatible iterator variants")
         return SomeIterator(s_cont, *iter1.variant)
 
 
@@ -778,8 +782,7 @@
         if (bltn1.analyser != bltn2.analyser or
             bltn1.methodname != bltn2.methodname or
             bltn1.s_self is None or bltn2.s_self is None):
-            raise UnionError("cannot merge two different builtin functions "
-                             "or methods:\n  %r\n  %r" % (bltn1, bltn2))
+            raise UnionError(bltn1, bltn2)
         s_self = unionof(bltn1.s_self, bltn2.s_self)
         return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
 
@@ -976,8 +979,8 @@
 
 class __extend__(pairtype(SomeAddress, SomeObject)):
     def union((s_addr, s_obj)):
-        raise UnionError, "union of address and anything else makes no sense"
+        raise UnionError(s_addr, s_obj)
 
 class __extend__(pairtype(SomeObject, SomeAddress)):
     def union((s_obj, s_addr)):
-        raise UnionError, "union of address and anything else makes no sense"
+        raise UnionError(s_obj, s_addr)
diff --git a/rpython/annotator/listdef.py b/rpython/annotator/listdef.py
--- a/rpython/annotator/listdef.py
+++ b/rpython/annotator/listdef.py
@@ -58,7 +58,7 @@
     def merge(self, other):
         if self is not other:
             if getattr(TLS, 'no_side_effects_in_union', 0):
-                raise UnionError("merging list/dict items")
+                raise UnionError(self, other)
 
             if other.dont_change_any_more:
                 if self.dont_change_any_more:
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -680,6 +680,33 @@
     """Signals an suspicious attempt at taking the union of
     deeply incompatible SomeXxx instances."""
 
+    def __init__(self, s_obj1, s_obj2, msg=None):
+        """
+        This exception expresses the fact that s_obj1 and s_obj2 cannot be 
unified.
+        The msg paramter is appended to a generic message. This can be used to
+        give the user a little more information.
+        """
+        self.s_obj1 = s_obj1
+        self.s_obj2 = s_obj2
+        self.msg = msg
+        self.source = None
+
+    def __str__(self):
+        s = "\n\n"
+
+        if self.msg is not None:
+            s += "%s\n\n" % self.msg
+
+        s += "Offending annotations:\n"
+        s += "%s\n%s\n\n" % (self.s_obj1, self.s_obj2)
+
+        if self.source is not None:
+            s += self.source
+
+        return s
+
+    def __repr__(self):
+        return str(self)
 
 def unionof(*somevalues):
     "The most precise SomeValue instance that contains all the values."
diff --git a/rpython/annotator/test/test_annrpython.py 
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4023,6 +4023,81 @@
         a = self.RPythonAnnotator()
         assert not a.build_types(fn, [int]).nonneg
 
+    def test_unionerror_attrs(self):
+        def f(x):
+            if x < 10:
+                return 1
+            else:
+                return "bbb"
+        a = self.RPythonAnnotator()
+
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f, [int])
+
+        the_exc = exc.value
+        s_objs = set([type(the_exc.s_obj1), type(the_exc.s_obj2)])
+
+        assert s_objs == set([annmodel.SomeInteger, annmodel.SomeString])
+        assert the_exc.msg == None # Check that this is a generic UnionError
+
+    def test_unionerror_tuple_size(self):
+        def f(x):
+            if x < 10:
+                return (1, )
+            else:
+                return (1, 2)
+        a = self.RPythonAnnotator()
+
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f, [int])
+
+        assert exc.value.msg == "RPython cannot unify tuples of different 
length: 2 versus 1"
+
+    def test_unionerror_signedness(self):
+        def f(x):
+            if x < 10:
+                return r_uint(99)
+            else:
+                return -1
+        a = self.RPythonAnnotator()
+
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f, [int])
+
+        assert exc.value.msg == ("RPython cannot prove that these integers are 
of "
+                "the same signedness")
+
+    def test_unionerror_instance(self):
+        class A(object): pass
+        class B(object): pass
+
+        def f(x):
+            if x < 10:
+                return A()
+            else:
+                return B()
+        a = self.RPythonAnnotator()
+
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f, [int])
+
+        assert exc.value.msg == ("RPython cannot unify instances with no 
common base class")
+
+    def test_unionerror_iters(self):
+
+        def f(x):
+            d = { 1 : "a", 2 : "b" }
+            if x < 10:
+                return d.iterkeys()
+            else:
+                return d.itervalues()
+        a = self.RPythonAnnotator()
+
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f, [int])
+
+        assert exc.value.msg == ("RPython cannot unify incompatible iterator 
variants")
+
 def g(n):
     return [0, 1, 2, n]
 
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -24,8 +24,9 @@
         self.frame = frame
 
     def __str__(self):
-        msg = ['-+' * 30]
+        msg = ["\n"]
         msg += map(str, self.args)
+        msg += [""]
         msg += source_lines(self.frame.graph, None, 
offset=self.frame.last_instr)
         return "\n".join(msg)
 
@@ -293,7 +294,7 @@
 
 _unsupported_ops = [
     ('BINARY_POWER', "a ** b"),
-    ('BUILD_CLASS', 'creating new classes'),
+    ('BUILD_CLASS', 'defining classes inside functions'),
     ('EXEC_STMT', 'exec statement'),
     ('STOP_CODE', '???'),
     ('STORE_NAME', 'modifying globals'),
diff --git a/rpython/jit/backend/arm/locations.py 
b/rpython/jit/backend/arm/locations.py
--- a/rpython/jit/backend/arm/locations.py
+++ b/rpython/jit/backend/arm/locations.py
@@ -33,6 +33,9 @@
     def get_position(self):
         raise NotImplementedError # only for stack
 
+    def get_jitframe_position(self):
+        raise NotImplementedError
+
 class RegisterLocation(AssemblerLocation):
     _immutable_ = True
     width = WORD
diff --git a/rpython/jit/backend/arm/opassembler.py 
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -46,6 +46,26 @@
         self.fcond = fcond
         self.offset = offset
 
+    def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth):
+        # note that this is an old version that should not be here in
+        # the first place. Implement get_jitframe_position on ARM locations
+        # in order to make it work, then kill this function
+        input_i = 0
+        for i in range(len(failargs)):
+            arg = failargs[i]
+            if arg is None:
+                continue
+            loc = fail_locs[input_i]
+            input_i += 1
+            if arg.type == REF:
+                loc = fail_locs[i]
+                if loc.is_core_reg():
+                    val = self.cpu.all_reg_indexes[loc.value]
+                else:
+                    val = loc.get_position() + self.cpu.JITFRAME_FIXED_SIZE
+                gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
+        return gcmap
+
 
 class ResOpAssembler(BaseAssembler):
 
diff --git a/rpython/jit/backend/llsupport/assembler.py 
b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -36,22 +36,12 @@
         self.is_guard_not_forced = is_guard_not_forced
 
     def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth):
-        # note that regalloc has a very similar compute, but
-        # one that does iteration over all bindings, so slightly different,
-        # eh
-        input_i = 0
         for i in range(len(failargs)):
             arg = failargs[i]
             if arg is None:
                 continue
-            loc = fail_locs[input_i]
-            input_i += 1
             if arg.type == REF:
-                loc = fail_locs[i]
-                if loc.is_core_reg():
-                    val = self.cpu.all_reg_indexes[loc.value]
-                else:
-                    val = loc.get_position() + self.cpu.JITFRAME_FIXED_SIZE
+                val = fail_locs[i].get_jitframe_position()
                 gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
         return gcmap
 
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1772,17 +1772,13 @@
             regs = gpr_reg_mgr_cls.all_regs
         for gpr in regs:
             if gpr not in ignored_regs:
-                v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
+                v = gpr.get_jitframe_position()
                 mc.MOV_br(v * WORD + base_ofs, gpr.value)
         if withfloats:
-            if IS_X86_64:
-                coeff = 1
-            else:
-                coeff = 2
             # Push all XMM regs
-            ofs = len(gpr_reg_mgr_cls.all_regs)
-            for i in range(len(xmm_reg_mgr_cls.all_regs)):
-                mc.MOVSD_bx((ofs + i * coeff) * WORD + base_ofs, i)
+            for reg in xmm_reg_mgr_cls.all_regs:
+                v = reg.get_jitframe_position()
+                mc.MOVSD_bx(v * WORD + base_ofs, reg.value)
 
     def _pop_all_regs_from_frame(self, mc, ignored_regs, withfloats,
                                  callee_only=False):
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -898,12 +898,12 @@
             if box.type == REF and self.rm.is_still_alive(box):
                 assert not noregs
                 assert isinstance(loc, RegLoc)
-                val = gpr_reg_mgr_cls.all_reg_indexes[loc.value]
+                val = loc.get_jitframe_position()
                 gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
         for box, loc in self.fm.bindings.iteritems():
             if box.type == REF and self.rm.is_still_alive(box):
                 assert isinstance(loc, FrameLoc)
-                val = loc.position + JITFRAME_FIXED_SIZE
+                val = loc.get_jitframe_position()
                 gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
         return gcmap
 
diff --git a/rpython/jit/backend/x86/regloc.py 
b/rpython/jit/backend/x86/regloc.py
--- a/rpython/jit/backend/x86/regloc.py
+++ b/rpython/jit/backend/x86/regloc.py
@@ -1,5 +1,6 @@
 from rpython.jit.metainterp.history import ConstInt
 from rpython.jit.backend.x86 import rx86
+from rpython.jit.backend.x86.arch import JITFRAME_FIXED_SIZE
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.jit.backend.x86.arch import WORD, IS_X86_32, IS_X86_64
 from rpython.tool.sourcetools import func_with_new_name
@@ -51,6 +52,8 @@
     def get_position(self):
         raise NotImplementedError # only for stack
 
+    def get_jitframe_position(self):
+        raise NotImplementedError
 
 class RawEbpLoc(AssemblerLocation):
     """ The same as stack location, but does not know it's position.
@@ -129,6 +132,9 @@
     def get_position(self):
         return self.position
 
+    def get_jitframe_position(self):
+        return self.position + JITFRAME_FIXED_SIZE
+
 class RegLoc(AssemblerLocation):
     _immutable_ = True
     def __init__(self, regnum, is_xmm):
@@ -173,6 +179,18 @@
     def is_core_reg(self):
         return True
 
+    def get_jitframe_position(self):
+        from rpython.jit.backend.x86 import regalloc
+
+        if self.is_xmm:
+            ofs = len(regalloc.gpr_reg_mgr_cls.all_regs)
+            if IS_X86_64:
+                return ofs + self.value
+            else:
+                return ofs + 2 * self.value
+        else:
+            return regalloc.gpr_reg_mgr_cls.all_reg_indexes[self.value]
+
 class ImmediateAssemblerLocation(AssemblerLocation):
     _immutable_ = True
 
diff --git a/rpython/tool/error.py b/rpython/tool/error.py
--- a/rpython/tool/error.py
+++ b/rpython/tool/error.py
@@ -90,7 +90,7 @@
             format_simple_call(annotator, oper, msg)
     else:
         oper = None
-    msg.append(" " + str(oper))
+    msg.append("    %s\n" % str(oper))
     msg += source_lines(graph, block, operindex, long=True)
     if oper is not None:
         if SHOW_ANNOTATIONS:
@@ -106,7 +106,7 @@
 def format_blocked_annotation_error(annotator, blocked_blocks):
     text = []
     for block, (graph, index) in blocked_blocks.items():
-        text.append('-+' * 30)
+        text.append('\n')
         text.append("Blocked block -- operation cannot succeed")
         text.append(gather_error(annotator, graph, block, index))
     return '\n'.join(text)
diff --git a/rpython/translator/goal/translate.py 
b/rpython/translator/goal/translate.py
--- a/rpython/translator/goal/translate.py
+++ b/rpython/translator/goal/translate.py
@@ -246,17 +246,19 @@
         tb = None
         if got_error:
             import traceback
-            errmsg = ["Error:\n"]
+            stacktrace_errmsg = ["Error:\n"]
             exc, val, tb = sys.exc_info()
-            errmsg.extend([" %s" % line for line in 
traceback.format_exception(exc, val, tb)])
+            stacktrace_errmsg.extend([" %s" % line for line in 
traceback.format_tb(tb)])
+            summary_errmsg = traceback.format_exception_only(exc, val)
             block = getattr(val, '__annotator_block', None)
             if block:
                 class FileLike:
                     def write(self, s):
-                        errmsg.append(" %s" % s)
-                errmsg.append("Processing block:\n")
+                        summary_errmsg.append(" %s" % s)
+                summary_errmsg.append("Processing block:\n")
                 t.about(block, FileLike())
-            log.ERROR(''.join(errmsg))
+            log.info(''.join(stacktrace_errmsg))
+            log.ERROR(''.join(summary_errmsg))
         else:
             log.event('Done.')
 
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to