[pypy-commit] pypy refactor-signature: refactor up to a nice point of segmentation fault

fijal noreply at buildbot.pypy.org
Wed Dec 14 12:22:59 CET 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: refactor-signature
Changeset: r50496:8fc2393b390b
Date: 2011-12-14 13:22 +0200
http://bitbucket.org/pypy/pypy/changeset/8fc2393b390b/

Log:	refactor up to a nice point of segmentation fault

diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py
--- a/pypy/module/micronumpy/interp_iter.py
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -2,13 +2,6 @@
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import instantiate
 
-class NumpyEvalFrame(object):
-    def __init__(self, iterators):
-        self.iterators = iterators
-
-    def next(self, shapelen):
-        xxx
-
 # Iterators for arrays
 # --------------------
 # all those iterators with the exception of BroadcastIterator iterate over the
@@ -159,38 +152,6 @@
     def get_offset(self):
         return self.offset
 
-class Call2Iterator(BaseIterator):
-    def __init__(self, left, right):
-        self.left = left
-        self.right = right
-
-    def next(self, shapelen):
-        return Call2Iterator(self.left.next(shapelen),
-                             self.right.next(shapelen))
-
-    def done(self):
-        if isinstance(self.left, ConstantIterator):
-            return self.right.done()
-        return self.left.done()
-
-    def get_offset(self):
-        if isinstance(self.left, ConstantIterator):
-            return self.right.get_offset()
-        return self.left.get_offset()
-
-class Call1Iterator(BaseIterator):
-    def __init__(self, child):
-        self.child = child
-
-    def next(self, shapelen):
-        return Call1Iterator(self.child.next(shapelen))
-
-    def done(self):
-        return self.child.done()
-
-    def get_offset(self):
-        return self.child.get_offset()
-
 class ConstantIterator(BaseIterator):
     def next(self, shapelen):
         return self
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
@@ -7,11 +7,12 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.rstring import StringBuilder
-from pypy.module.micronumpy.interp_iter import NumpyEvalFrame, ArrayIterator
+from pypy.module.micronumpy.interp_iter import ArrayIterator
 
 numpy_driver = jit.JitDriver(
     greens=['shapelen', 'signature'],
-    reds=['result_size', 'i', 'ri', 'self', 'result']
+    virtualizables=['frame'],
+    reds=['result_size', 'frame', 'ri', 'self', 'result']
 )
 all_driver = jit.JitDriver(
     greens=['shapelen', 'signature'],
@@ -759,9 +760,6 @@
     def getitem(self, item):
         raise NotImplementedError
 
-    def eval(self, iter):
-        return self.value
-
     def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
         builder.append(self.dtype.itemtype.str_format(self.value))
 
@@ -790,20 +788,22 @@
         raise NotImplementedError
 
     def compute(self):
-        i = 0
         result_size = self.find_size()
         result = W_NDimArray(result_size, self.shape, self.find_dtype())
         shapelen = len(self.shape)
-        xxx
-        i = self.start_iter()
-        ri = result.start_iter()
+        signature = self.find_sig()
+        frame = signature.create_frame(self)
+        ri = ArrayIterator(result)
         while not ri.done():
             numpy_driver.jit_merge_point(signature=signature,
                                          shapelen=shapelen,
-                                         result_size=result_size, i=i, ri=ri,
+                                         result_size=result_size,
+                                         frame=frame,
+                                         ri=ri,
                                          self=self, result=result)
-            result.dtype.setitem(result.storage, ri.offset, self.eval(i))
-            i = i.next(shapelen)
+            result.dtype.setitem(result.storage, ri.offset,
+                                 signature.eval(frame, self))
+            frame.next(shapelen)
             ri = ri.next(shapelen)
         return result
 
@@ -816,11 +816,6 @@
         self.force_if_needed()
         return self.forced_result
 
-    def eval(self, iter):
-        if self.forced_result is not None:
-            return self.forced_result.eval(iter)
-        return self._eval(iter)
-
     def getitem(self, item):
         return self.get_concrete().getitem(item)
 
@@ -853,14 +848,9 @@
     def _find_dtype(self):
         return self.res_dtype
 
-    def _eval(self, iter):
-        assert isinstance(iter, Call1Iterator)
-        val = self.values.eval(iter.child).convert_to(self.res_dtype)
-        sig = jit.promote(self.signature)
-        assert isinstance(sig, signature.Call1)
-        return sig.unfunc(self.res_dtype, val)
-
     def create_sig(self):
+        if self.forced_result is not None:
+            return self.forced_result.create_sig()
         return signature.Call1(self.ufunc, self.values.create_sig())
 
 class Call2(VirtualArray):
@@ -884,15 +874,9 @@
     def _find_size(self):
         return self.size
 
-    def _eval(self, iter):
-        assert isinstance(iter, Call2Iterator)
-        lhs = self.left.eval(iter.left).convert_to(self.calc_dtype)
-        rhs = self.right.eval(iter.right).convert_to(self.calc_dtype)
-        sig = jit.promote(self.signature)
-        assert isinstance(sig, signature.Call2)
-        return sig.binfunc(self.calc_dtype, lhs, rhs)
-
     def create_sig(self):
+        if self.forced_result is not None:
+            return self.forced_result.create_sig()
         return signature.Call2(self.ufunc, self.left.create_sig(),
                                self.right.create_sig())
 
@@ -1048,9 +1032,6 @@
     def getitem(self, item):
         return self.dtype.getitem(self.storage, item)
 
-    def eval(self, iter):
-        return self.dtype.getitem(self.storage, iter.get_offset())
-
     def copy(self):
         array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
         rffi.c_memcpy(
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -1,8 +1,7 @@
-from pypy.rlib.objectmodel import r_dict, compute_identity_hash, compute_hash
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.objectmodel import r_dict, compute_identity_hash
 from pypy.module.micronumpy.interp_iter import ViewIterator, ArrayIterator, \
      BroadcastIterator, OneDimIterator, ConstantIterator
-
+from pypy.rlib.jit import hint, unroll_safe
 
 # def components_eq(lhs, rhs):
 #     if len(lhs) != len(rhs):
@@ -30,10 +29,19 @@
 def find_sig(sig):
     return known_sigs.setdefault(sig, sig)
 
+class NumpyEvalFrame(object):
+    _virtualizable2_ = ['iterators[*]']
+
+    def __init__(self, iterators):
+        self = hint(self, access_directly=True)
+        self.iterators = iterators
+
+    @unroll_safe
+    def next(self, shapelen):
+        for i in range(len(self.iterators)):
+            self.iterators[i] = self.iterators[i].next(shapelen)
+
 class Signature(object):
-    def create_iter(self, array, cache, res_shape=None):
-        raise NotImplementedError
-
     def invent_numbering(self):
         cache = r_dict(sigeq, sighash)
         self._invent_numbering(cache)
@@ -44,7 +52,12 @@
         except KeyError:
             no = len(cache)
             cache[self] = no
-        self.iter_no = no    
+        self.iter_no = no
+
+    def create_frame(self, arr, res_shape=None):
+        iterlist = []
+        self._create_iter(iterlist, arr, res_shape)
+        return NumpyEvalFrame(iterlist)
 
 class ConcreteSignature(Signature):
     def __init__(self, dtype):
@@ -62,10 +75,27 @@
     def debug_repr(self):
         return 'Array'
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        if self.iter_no >= len(iterlist):
+            iter = ArrayIterator(arr)
+            iterlist.append(iter)
+
+    def eval(self, frame, arr):
+        iter = frame.iterators[self.iter_no]
+        return arr.dtype.getitem(arr.storage, iter.offset)
+
 class ScalarSignature(ConcreteSignature):
     def debug_repr(self):
         return 'Scalar'
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        if self.iter_no >= len(iterlist):
+            iter = ConstantIterator()
+            iterlist.append(iter)
+
+    def eval(self, frame, arr):
+        return arr.value
+
 class ViewSignature(Signature):
     def __init__(self, child):
         self.child = child
@@ -81,10 +111,18 @@
     def debug_repr(self):
         return 'Slice(%s)' % self.child.debug_repr()
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        if self.iter_no >= len(iterlist):
+            iter = ViewIterator(arr)
+            iterlist.append(iter)
+
 class FlatiterSignature(ViewSignature):
     def debug_repr(self):
         return 'FlatIter(%s)' % self.child.debug_repr()
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        XXX
+
 class Call1(Signature):
     def __init__(self, func, child):
         self.unfunc = func
@@ -105,6 +143,13 @@
     def _invent_numbering(self, cache):
         self.values._invent_numbering(cache)
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        self.child._create_iter(iterlist, arr.values, res_shape)
+
+    def eval(self, frame, arr):
+        v = self.child.eval(frame, arr.values).convert_to(arr.res_dtype)
+        return self.unfunc(arr.res_dtype, v)
+
 class Call2(Signature):
     def __init__(self, func, left, right):
         self.binfunc = func
@@ -125,6 +170,15 @@
         self.left._invent_numbering(cache)
         self.right._invent_numbering(cache)
 
+    def _create_iter(self, iterlist, arr, res_shape):
+        self.left._create_iter(iterlist, arr.left, res_shape)
+        self.right._create_iter(iterlist, arr.right, res_shape)
+
+    def eval(self, frame, arr):
+        lhs = self.left.eval(frame, arr.left).convert_to(arr.calc_dtype)
+        rhs = self.right.eval(frame, arr.right).convert_to(arr.calc_dtype)
+        return self.binfunc(arr.calc_dtype, lhs, rhs)
+
     def debug_repr(self):
         return 'Call2(%s, %s, %s)' % (self.name,
                                       self.left.debug_repr(),
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -39,6 +39,8 @@
         assert sig7.left.left.iter_no == sig7.right.left.iter_no
         assert sig7.left.left.iter_no != sig7.right.right.iter_no
         assert sig7.left.right.iter_no == sig7.right.right.iter_no
+        v1.forced_result = ar
+        assert v1.find_sig() is not sig1
 
     def test_slice_signature(self, space):
         float64_dtype = get_dtype_cache(space).w_float64dtype


More information about the pypy-commit mailing list