Commits

Armin Rigo committed 1860c27

Not absolutely necessary for now, but allows cleaner code:
if x is a symbolic offset from llmemory, and if it clearly
cannot be negative, then "x >= 0" works (and returns True).
Can be used to distinguish between such a symbolic offset
and a special value like -1.

Comments (0)

Files changed (4)

pypy/rpython/lltypesystem/llarena.py

     def __repr__(self):
         return '< RoundedUpForAllocation %r >' % (self.basesize,)
 
+    def known_nonneg(self):
+        return self.basesize.known_nonneg()
+
     def ref(self, ptr):
         return self.basesize.ref(ptr)
 

pypy/rpython/lltypesystem/llmemory.py

             return NotImplemented
         return CompositeOffset(self, other)
 
+    # special-casing: only for '>= 0' and '< 0' and only when the
+    # symbolic offset is known to be non-negative
+    def __ge__(self, other):
+        if self is other:
+            return True
+        elif (isinstance(other, (int, long)) and other == 0 and
+            self.known_nonneg()):
+            return True
+        else:
+            raise TypeError("Symbolics can not be compared!")
+
+    def __lt__(self, other):
+        return not self.__ge__(other)
+
+    def known_nonneg(self):
+        return False
+
     def _raw_malloc(self, rest, zero):
         raise NotImplementedError("_raw_malloc(%r, %r)" % (self, rest))
 
     def __neg__(self):
         return ItemOffset(self.TYPE, -self.repeat)
 
+    def known_nonneg(self):
+        return self.repeat >= 0
+
     def ref(self, firstitemptr):
         A = lltype.typeOf(firstitemptr).TO
         if A == self.TYPE:
     def __repr__(self):
         return "<FieldOffset %r %r>" % (self.TYPE, self.fldname)
 
+    def known_nonneg(self):
+        return True
+
     def ref(self, struct):
         if lltype.typeOf(struct).TO != self.TYPE:
             struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
         ofs.reverse()
         return CompositeOffset(*ofs)
 
+    def known_nonneg(self):
+        for item in self.offsets:
+            if not item.known_nonneg():
+                return False
+        return True
+
     def ref(self, ptr):
         for item in self.offsets:
             ptr = item.ref(ptr)
     def __repr__(self):
         return '< ArrayItemsOffset %r >' % (self.TYPE,)
 
+    def known_nonneg(self):
+        return True
+
     def ref(self, arrayptr):
         assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
         if isinstance(self.TYPE.OF, lltype.ContainerType):
     def __repr__(self):
         return '< ArrayLengthOffset %r >' % (self.TYPE,)
 
+    def known_nonneg(self):
+        return True
+
     def ref(self, arrayptr):
         assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
         return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
     def __neg__(self):
         return GCHeaderAntiOffset(self.gcheaderbuilder)
 
+    def known_nonneg(self):
+        return True
+
     def ref(self, headerptr):
         gcptr = self.gcheaderbuilder.object_from_header(headerptr)
         return gcptr

pypy/rpython/lltypesystem/test/test_llmemory.py

     src = cast_ptr_to_adr(a) + itemoffsetof(A, 0)
     raw_memclear(src, sizeof(lltype.Signed) * 0)
     
+def test_nonneg():
+    S1 = lltype.GcStruct('S1', ('x', lltype.Float))
+    A1 = lltype.GcArray(lltype.Float)
+    assert sizeof(S1) >= 0
+    assert itemoffsetof(A1, 4) >= 0
+    assert not (sizeof(S1) < 0)
+    assert not (itemoffsetof(A1, 4) < 0)
+    py.test.raises(TypeError, "sizeof(S1) > 0")
+    py.test.raises(TypeError, "sizeof(S1) > 1")
+    py.test.raises(TypeError, "sizeof(S1) <= 0")
+    py.test.raises(TypeError, "sizeof(S1) <= 4")
+    py.test.raises(TypeError, "(-sizeof(S1)) >= 0")

pypy/rpython/memory/gc/base.py

 
         size = self.fixed_size(typeid)
         needs_finalizer = bool(self.getfinalizer(typeid))
-        weakptr_offset = self.weakpointer_offset(typeid)
-        #XXX cannot compare weakptr_offset with -1
-        #contains_weakptr = weakpointer_offset. != -1
-        if isinstance(weakptr_offset, int):
-            assert weakptr_offset == -1
-            contains_weakptr = False
-        else:
-            contains_weakptr = True
+        contains_weakptr = self.weakpointer_offset(typeid) >= 0
         assert not (needs_finalizer and contains_weakptr)
         if self.is_varsize(typeid):
             assert not contains_weakptr