[pypy-svn] r34767 - in pypy/dist/pypy: rlib rpython rpython/lltypesystem translator/backendopt translator/c translator/c/src translator/llvm

arigo at codespeak.net arigo at codespeak.net
Sun Nov 19 19:25:56 CET 2006


Author: arigo
Date: Sun Nov 19 19:25:50 2006
New Revision: 34767

Modified:
   pypy/dist/pypy/rlib/objectmodel.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/opimpl.py
   pypy/dist/pypy/rpython/lltypesystem/rlist.py
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/src/support.h
   pypy/dist/pypy/translator/llvm/opwriter.py
Log:
(pedronis, arigo)

A more persistent 'debug_assert' operation, with a nice function interface
in objectmodel too.  Unknown overhead :-(

It is compiled to a call to the C macro RPyAssert(), which is by default
#defined to nothing.  To enable, use any of the makefile's "debug"
targets.

Added a lot of debug_assert() in rlist.  Now a debug-compiled pypy-c
should no longer be able to crash obscurely after it popped from an
empty list.



Modified: pypy/dist/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rlib/objectmodel.py	(original)
+++ pypy/dist/pypy/rlib/objectmodel.py	Sun Nov 19 19:25:50 2006
@@ -190,8 +190,23 @@
                          resulttype = hop.r_result.lowleveltype)
 
 
-   
-# __ hlinvoke XXX this doesn't seem completely the right place for this
+def debug_assert(x, msg):
+    """After translation to C, this becomes an RPyAssert."""
+    assert x, msg
+
+class Entry(ExtRegistryEntry):
+    _about_ = debug_assert
+
+    def compute_result_annotation(self, s_x, s_msg):
+        assert s_msg.is_constant(), ("debug_assert(x, msg): "
+                                     "the msg must be constant")
+        return None
+
+    def specialize_call(self, hop):
+        from pypy.rpython.lltypesystem import lltype
+        vlist = hop.inputargs(lltype.Bool, lltype.Void)
+        hop.genop('debug_assert', vlist)
+
 
 def hlinvoke(repr, llcallable, *args):
     raise TypeError, "hlinvoke is meant to be rtyped and not called direclty"

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sun Nov 19 19:25:50 2006
@@ -448,9 +448,8 @@
         import pdb
         pdb.set_trace()
 
-    def op_debug_log_exc(self, exc_type):
-        # do nothing, this is useful in compiled code
-        pass
+    def op_debug_assert(self, x, msg):
+        assert x, msg
 
     def op_debug_fatalerror(self, ll_msg, ll_exc=None):
         msg = ''.join(ll_msg.chars)

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sun Nov 19 19:25:50 2006
@@ -399,7 +399,7 @@
     'debug_view':           LLOp(),
     'debug_print':          LLOp(),
     'debug_pdb':            LLOp(),
-    'debug_assert':         LLOp(canfold=True),
+    'debug_assert':         LLOp(),
     'debug_fatalerror':     LLOp(),
 
     # __________ instrumentation _________

Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/opimpl.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py	Sun Nov 19 19:25:50 2006
@@ -359,20 +359,6 @@
         raise TypeError("cannot fold getfield on mutable array")
     return p[index]
 
-
-def op_debug_assert(expr, *ll_args):
-    if not isinstance(expr, str):
-        if hasattr(expr, 'chars'):       # for lltypesystem
-            expr = ''.join(expr.chars)
-        elif hasattr(expr, '_str'):      # for ootypesystem
-            expr = expr._str
-        else:
-            raise TypeError("what is %r??" % (expr,))
-    names = ['v%d' % i for i in range(len(ll_args))]
-    d = dict(zip(names, ll_args))
-    names = tuple(names)
-    assert eval(expr % names, d)
-
 # ____________________________________________________________
 
 def get_op_impl(opname):

Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py	Sun Nov 19 19:25:50 2006
@@ -16,6 +16,7 @@
      Bool, nullptr, typeMethod
 from pypy.rpython.lltypesystem import rstr
 from pypy.rpython import robject
+from pypy.rlib.objectmodel import debug_assert
 
 # ____________________________________________________________
 #
@@ -374,6 +375,7 @@
 #  Accessor methods
 
 def ll_newlist(LIST, length):
+    debug_assert(length >= 0, "negative list length")
     l = malloc(LIST)
     l.length = length
     l.items = malloc(LIST.items.TO, length)
@@ -387,19 +389,18 @@
 def ll_items(l):
     return l.items
 
-from pypy.rpython.lltypesystem.lloperation import llop
-
 def ll_getitem_fast(l, index):
-    llop.debug_assert(Void, "%s < %s.length # getitem out of bounds", index, l)
+    debug_assert(index < l.length, "getitem out of bounds")
     return l.ll_items()[index]
 
 def ll_setitem_fast(l, index, item):
-    llop.debug_assert(Void, "%s < %s.length # setitem out of bounds", index, l)
+    debug_assert(index < l.length, "setitem out of bounds")
     l.ll_items()[index] = item
 
 # fixed size versions
 
 def ll_fixed_newlist(LIST, length):
+    debug_assert(length >= 0, "negative fixed list length")
     l = malloc(LIST, length)
     return l
 ll_fixed_newlist = typeMethod(ll_fixed_newlist)
@@ -412,9 +413,11 @@
     return l
 
 def ll_fixed_getitem_fast(l, index):
+    debug_assert(index < len(l), "fixed getitem out of bounds")
     return l[index]
 
 def ll_fixed_setitem_fast(l, index, item):
+    debug_assert(index < len(l), "fixed setitem out of bounds")
     l[index] = item
 
 def newlist(llops, r_list, items_v):

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Sun Nov 19 19:25:50 2006
@@ -2,6 +2,7 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.rpython.error import TyperError
 from pypy.rlib.objectmodel import malloc_zero_filled, we_are_translated
+from pypy.rlib.objectmodel import debug_assert
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rlib.rarithmetic import _hash_string
 from pypy.rpython.rmodel import inputconst, IntegerRepr
@@ -109,10 +110,8 @@
                                  resulttype=pyobj_repr,
                                  _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
 
-from pypy.rpython.lltypesystem.lloperation import llop
-
 def mallocstr(length):
-    llop.debug_assert(Void, "%s >= 0 # negative string length", length)
+    debug_assert(length >= 0, "negative string length")
     r = malloc(STR, length)
     if not we_are_translated() or not malloc_zero_filled:
         r.hash = 0

Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Sun Nov 19 19:25:50 2006
@@ -6,9 +6,8 @@
 from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool
 from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar
-from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython import robject
-from pypy.rlib.objectmodel import malloc_zero_filled
+from pypy.rlib.objectmodel import malloc_zero_filled, debug_assert
 from pypy.rpython.annlowlevel import ADTInterface
 
 ADTIFixedList = ADTInterface(None, {
@@ -474,6 +473,8 @@
 
 def ll_insert_nonneg(l, index, newitem):
     length = l.ll_length()
+    debug_assert(0 <= index, "negative list insertion index")
+    debug_assert(index <= length, "list insertion index out of bound")
     l._ll_resize_ge(length+1)
     dst = length
     while dst > index:
@@ -484,8 +485,12 @@
 ll_insert_nonneg.oopspec = 'list.insert(l, index, newitem)'
 
 def ll_pop_nonneg(func, l, index):
-    if func is dum_checkidx and (index >= l.ll_length()):
-        raise IndexError
+    debug_assert(index >= 0, "unexpectedly negative list pop index")
+    if func is dum_checkidx:
+        if index >= l.ll_length():
+            raise IndexError
+    else:
+        debug_assert(index < l.ll_length(), "list pop index out of bound")
     res = l.ll_getitem_fast(index)
     ll_delitem_nonneg(dum_nocheck, l, index)
     return res
@@ -495,6 +500,7 @@
     length = l.ll_length()
     if func is dum_checkidx and (length == 0):
         raise IndexError
+    debug_assert(length > 0, "pop from empty list")
     index = length - 1
     newlength = index
     res = l.ll_getitem_fast(index)
@@ -509,6 +515,7 @@
     length = l.ll_length()
     if func is dum_checkidx and (length == 0):
         raise IndexError
+    debug_assert(length > 0, "pop(0) from empty list")
     newlength = length - 1
     res = l.ll_getitem_fast(0)
     j = 0
@@ -528,8 +535,12 @@
     length = l.ll_length()
     if index < 0:
         index += length
-    if func is dum_checkidx and (index < 0 or index >= length):
-        raise IndexError
+    if func is dum_checkidx:
+        if index < 0 or index >= length:
+            raise IndexError
+    else:
+        debug_assert(index >= 0, "negative list pop index out of bound")
+        debug_assert(index < length, "list pop index out of bound")
     res = l.ll_getitem_fast(index)
     ll_delitem_nonneg(dum_nocheck, l, index)
     return res
@@ -548,8 +559,12 @@
 ll_reverse.oopspec = 'list.reverse(l)'
 
 def ll_getitem_nonneg(func, l, index):
-    if func is dum_checkidx and (index >= l.ll_length()):
-        raise IndexError
+    debug_assert(index >= 0, "unexpectedly negative list getitem index")
+    if func is dum_checkidx:
+        if index >= l.ll_length():
+            raise IndexError
+    else:
+        debug_assert(index < l.ll_length(), "list getitem index out of bound")
     return l.ll_getitem_fast(index)
 ll_getitem_nonneg.oopspec = 'list.getitem(l, index)'
 
@@ -557,14 +572,22 @@
     length = l.ll_length()
     if index < 0:
         index += length
-    if func is dum_checkidx and (index < 0 or index >= length):
-        raise IndexError
+    if func is dum_checkidx:
+        if index < 0 or index >= length:
+            raise IndexError
+    else:
+        debug_assert(index >= 0, "negative list getitem index out of bound")
+        debug_assert(index < length, "list getitem index out of bound")
     return l.ll_getitem_fast(index)
 ll_getitem.oopspec = 'list.getitem(l, index)'
 
 def ll_setitem_nonneg(func, l, index, newitem):
-    if func is dum_checkidx and (index >= l.ll_length()):
-        raise IndexError
+    debug_assert(index >= 0, "unexpectedly negative list setitem index")
+    if func is dum_checkidx:
+        if index >= l.ll_length():
+            raise IndexError
+    else:
+        debug_assert(index < l.ll_length(), "list setitem index out of bound")
     l.ll_setitem_fast(index, newitem)
 ll_setitem_nonneg.oopspec = 'list.setitem(l, index, newitem)'
 
@@ -572,15 +595,23 @@
     length = l.ll_length()
     if index < 0:
         index += length
-    if func is dum_checkidx and (index < 0 or index >= length):
-        raise IndexError
+    if func is dum_checkidx:
+        if index < 0 or index >= length:
+            raise IndexError
+    else:
+        debug_assert(index >= 0, "negative list setitem index out of bound")
+        debug_assert(index < length, "list setitem index out of bound")
     l.ll_setitem_fast(index, newitem)
 ll_setitem.oopspec = 'list.setitem(l, index, newitem)'
 
 def ll_delitem_nonneg(func, l, index):
+    debug_assert(index >= 0, "unexpectedly negative list delitem index")
     length = l.ll_length()
-    if func is dum_checkidx and (index >= length):
-        raise IndexError
+    if func is dum_checkidx:
+        if index >= length:
+            raise IndexError
+    else:
+        debug_assert(index < length, "list delitem index out of bound")
     newlength = length - 1
     j = index
     j1 = j+1
@@ -599,8 +630,12 @@
     length = l.ll_length()
     if i < 0:
         i += length
-    if func is dum_checkidx and (i < 0 or i >= length):
-        raise IndexError
+    if func is dum_checkidx:
+        if i < 0 or i >= length:
+            raise IndexError
+    else:
+        debug_assert(i >= 0, "negative list delitem index out of bound")
+        debug_assert(i < length, "list delitem index out of bound")
     ll_delitem_nonneg(dum_nocheck, l, i)
 ll_delitem.oopspec = 'list.delitem(l, i)'
 
@@ -619,6 +654,8 @@
 
 def ll_listslice_startonly(RESLIST, l1, start):
     len1 = l1.ll_length()
+    debug_assert(start >= 0, "unexpectedly negative list slice start")
+    debug_assert(start <= len1, "list slice start larger than list length")
     newlength = len1 - start
     l = RESLIST.ll_newlist(newlength)
     j = 0
@@ -633,6 +670,9 @@
     start = slice.start
     stop = slice.stop
     length = l1.ll_length()
+    debug_assert(start >= 0, "unexpectedly negative list slice start")
+    debug_assert(start <= length, "list slice start larger than list length")
+    debug_assert(stop >= start, "list slice stop smaller than start")
     if stop > length:
         stop = length
     newlength = stop - start
@@ -647,8 +687,7 @@
 
 def ll_listslice_minusone(RESLIST, l1):
     newlength = l1.ll_length() - 1
-    llop.debug_assert(Void, "%s >= 0 # empty list is sliced with [:-1]",
-                            newlength)
+    debug_assert(newlength >= 0, "empty list is sliced with [:-1]")
     l = RESLIST.ll_newlist(newlength)
     j = 0
     while j < newlength:
@@ -657,6 +696,8 @@
     return l
 
 def ll_listdelslice_startonly(l, start):
+    debug_assert(start >= 0, "del l[start:] with unexpectedly negative start")
+    debug_assert(start <= l.ll_length(), "del l[start:] with start > len(l)")
     newlength = start
     null = ll_null_item(l)
     if null is not None:
@@ -670,6 +711,9 @@
     start = slice.start
     stop = slice.stop
     length = l.ll_length()
+    debug_assert(start >= 0, "del l[start:x] with unexpectedly negative start")
+    debug_assert(start <= length, "del l[start:x] with start > len(l)")
+    debug_assert(stop >= start, "del l[x:y] with x > y")
     if stop > length:
         stop = length
     newlength = length - (stop-start)
@@ -689,11 +733,12 @@
 
 def ll_listsetslice(l1, slice, l2):
     count = l2.ll_length()
-    llop.debug_assert(Void,
-         "%s == %s - %s # setslice cannot resize lists in RPython",
-                      count, slice.stop, slice.start)
-    # XXX but it should be easy enough to support, soon
     start = slice.start
+    debug_assert(start >= 0, "l[start:x] = l with unexpectedly negative start")
+    debug_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)")
+    debug_assert(count == slice.stop - start,
+                 "setslice cannot resize lists in RPython")
+    # XXX but it should be easy enough to support, soon
     j = start
     i = 0
     while i < count:

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Sun Nov 19 19:25:50 2006
@@ -464,6 +464,7 @@
               'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
               'resume_point': sys.maxint, # XXX bit extreme
               'instrument_count': 0,
+              'debug_assert': -1,
               }
 
 def block_weight(block, weights=OP_WEIGHTS):
@@ -476,7 +477,7 @@
         total += weights.get(op.opname, 1)
     if block.exitswitch is not None:
         total += 1
-    return total
+    return max(0, total)
 
 
 def measure_median_execution_cost(graph):

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Sun Nov 19 19:25:50 2006
@@ -720,7 +720,8 @@
             ''.join([', ' + s for s in argv]))
 
     def OP_DEBUG_ASSERT(self, op):
-        return '/* debug_assert removed */'
+        return 'RPyAssert(%s, %s);' % (self.expr(op.args[0]),
+                                       c_string_constant(op.args[1].value))
 
     def OP_DEBUG_FATALERROR(self, op):
         # XXX

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Sun Nov 19 19:25:50 2006
@@ -859,13 +859,13 @@
 \trm -f $(OBJECTS) $(TARGET)
 
 debug:
-\tmake CFLAGS="-g"
+\tmake CFLAGS="-g -DRPY_ASSERT"
 
 debug_exc:
-\tmake CFLAGS="-g -DDO_LOG_EXC"
+\tmake CFLAGS="-g -DRPY_ASSERT -DDO_LOG_EXC"
 
 debug_mem:
-\tmake CFLAGS="-g -DNO_OBMALLOC"
+\tmake CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC"
 
 profile:
 \tmake CFLAGS="-pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)"

Modified: pypy/dist/pypy/translator/c/src/support.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/support.h	(original)
+++ pypy/dist/pypy/translator/c/src/support.h	Sun Nov 19 19:25:50 2006
@@ -25,6 +25,26 @@
 		memcpy(itemsarray->items, PyString_AS_STRING(s),        \
                        itemsarray->length)
 
+#ifdef RPY_ASSERT
+#  define RPyAssert(x, msg)                                             \
+     if (!(x)) RPyAssertFailed(__FILE__, __LINE__, __FUNCTION__, msg)
+
+void RPyAssertFailed(const char* filename, long lineno,
+                     const char* function, const char *msg);
+#  ifndef PYPY_NOT_MAIN_FILE
+void RPyAssertFailed(const char* filename, long lineno,
+                     const char* function, const char *msg) {
+  fprintf(stderr,
+          "PyPy assertion failed at %s:%d:\n"
+          "in %s: %s\n",
+          filename, lineno, function, msg);
+  abort();
+}
+#  endif
+#else
+#  define RPyAssert(x, msg)   /* nothing */
+#endif
+
 #ifdef __RPyListOfString_New     /*  :-(  */
 #  define HAVE_RPY_LIST_OF_STRING
 #endif

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Sun Nov 19 19:25:50 2006
@@ -172,11 +172,8 @@
     float_abs = int_abs
     llong_abs = int_abs
 
-    def debug_log_exc(self, opr):
-        # XXX tmp
-        pass
-
     def debug_assert(self, opr):
+        # XXX could do something about assertions
         pass
 
     def int_pow(self, opr):



More information about the Pypy-commit mailing list