Antonio Cuni avatar Antonio Cuni committed d520708

dump RawBuffer logs when something goes wrong

Comments (0)

Files changed (2)

pypy/jit/metainterp/optimizeopt/rawbuffer.py

+from pypy.rlib.debug import debug_start, debug_stop, debug_print
+from pypy.rlib.objectmodel import compute_unique_id, we_are_translated
+
 class InvalidRawOperation(Exception):
     pass
 
     pass
 
 class RawBuffer(object):
-    def __init__(self, cpu):
+    def __init__(self, cpu, logops=None):
         # the following lists represents the writes in the buffer: values[i]
         # is the value of length lengths[i] stored at offset[i].
         #
         # offset[i]+length[i] <= offset[i+1], i.e. that the writes never
         # overlaps
         self.cpu = cpu
+        self.logops = logops
         self.offsets = []
         self.lengths = []
         self.descrs = []
         """
         return zip(self.offsets, self.lengths, self.descrs, self.values)
 
+    def _repr_of_descr(self, descr):
+        if self.logops:
+            s = self.logops.repr_of_descr(descr)
+        else:
+            s = str(descr)
+        s += " at %d" % compute_unique_id(descr)
+        return s
+
+    def _repr_of_value(self, value):
+        if not we_are_translated() and isinstance(value, str):
+            return value # for tests
+        if self.logops:
+            s = self.logops.repr_of_arg(value.box)
+        else:
+            s = str(value.box)
+        s += " at %d" % compute_unique_id(value.box)
+        return s
+
+    def _dump_to_log(self):
+        debug_print("RawBuffer state")
+        debug_print("offset, length, descr, box")
+        debug_print("(box == None means that the value is still virtual)")
+        for i in range(len(self.offsets)):
+            descr = self._repr_of_descr(self.descrs[i])
+            box = self._repr_of_value(self.values[i])
+            debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box))
+
+    def _invalid_write(self, message, offset, length, descr, value):
+        debug_start('jit-log-rawbuffer')
+        debug_print('Invalid write: %s' % message)
+        debug_print("  offset: %d" % offset)
+        debug_print("  length: %d" % length)
+        debug_print("  descr:  %s" % self._repr_of_descr(descr))
+        debug_print("  value:  %s" % self._repr_of_value(value))
+        self._dump_to_log()
+        debug_stop('jit-log-rawbuffer')
+        raise InvalidRawWrite
+
+    def _invalid_read(self, message, offset, length, descr):
+        debug_start('jit-log-rawbuffer')
+        debug_print('Invalid read: %s' % message)
+        debug_print("  offset: %d" % offset)
+        debug_print("  length: %d" % length)
+        debug_print("  descr:  %s" % self._repr_of_descr(descr))
+        self._dump_to_log()
+        debug_stop('jit-log-rawbuffer')
+        raise InvalidRawRead
+
     def _descrs_are_compatible(self, d1, d2):
         # two arraydescrs are compatible if they have the same basesize,
         # itemsize and sign, even if they are not identical
                     # in theory we could add support for the cases in which
                     # the length or descr is different, but I don't think we
                     # need it in practice
-                    raise InvalidRawWrite
+                    self._invalid_write('length or descr not compatible',
+                                        offset, length, descr, value)
                 # update the value at this offset
                 self.values[i] = value
                 return
             i += 1
         #
         if i < len(self.offsets) and offset+length > self.offsets[i]:
-            raise InvalidRawWrite
+            self._invalid_write("overlap with next bytes",
+                                offset, length, descr, value)
         if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset:
-            raise InvalidRawWrite
+            self._invalid_write("overlap with previous bytes",
+                                offset, length, descr, value)
         # insert a new value at offset
         self.offsets.insert(i, offset)
         self.lengths.insert(i, length)
             if self.offsets[i] == offset:
                 if (length != self.lengths[i] or
                     not self._descrs_are_compatible(descr, self.descrs[i])):
-                    raise InvalidRawRead
+                    self._invalid_read('length or descr not compatible',
+                                       offset, length, descr)
                 return self.values[i]
             i += 1
         # memory location not found: this means we are reading from
         # uninitialized memory, give up the optimization
-        raise InvalidRawRead
+        self._invalid_read('uninitialized memory',
+                           offset, length, descr)

pypy/jit/metainterp/optimizeopt/virtualize.py

 
 class VRawBufferValue(AbstractVArrayValue):
 
-    def __init__(self, cpu, size, keybox, source_op):
+    def __init__(self, cpu, logops, size, keybox, source_op):
         AbstractVirtualValue.__init__(self, keybox, source_op)
         # note that size is unused, because we assume that the buffer is big
         # enough to write/read everything we need. If it's not, it's undefined
         # behavior anyway, although in theory we could probably detect such
         # cases here
         self.size = size
-        self.buffer = RawBuffer(cpu)
+        self.buffer = RawBuffer(cpu, logops)
 
     def getlength(self):
         return len(self.buffer.values)
         return vvalue
 
     def make_virtual_raw_memory(self, size, box, source_op):
-        vvalue = VRawBufferValue(self.optimizer.cpu, size, box, source_op)
+        logops = self.optimizer.loop.logops
+        vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op)
         self.make_equal_to(box, vvalue)
         return vvalue
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.