1. Pypy
  2. Untitled project
  3. pypy

Commits

Alex Gaynor  committed fb11c92

(arigato, fijal, alex): make untyped storage work with the GC, other things were refactored

  • Participants
  • Parent commits 6b75ec7
  • Branches erase-raw-mem

Comments (0)

Files changed (5)

File pypy/rlib/rerased_raw.py

View file
  • Ignore whitespace
 
 from pypy.annotation import model as annmodel
 from pypy.annotation.bookkeeper import getbookkeeper
-from pypy.rpython.annlowlevel import hlstr, llstr
+from pypy.rpython.annlowlevel import hlstr, llstr, llhelper
 from pypy.rpython.extregistry import ExtRegistryEntry
-from pypy.rpython.lltypesystem import rffi, lltype, llmemory, rstr
+from pypy.rpython.lltypesystem import rffi, lltype, llmemory
+from pypy.rpython.lltypesystem.rstr import STR, string_repr
 from pypy.rpython.rmodel import Repr
 
 
         self._check_idx(s_idx)
         assert isinstance(s_obj, annmodel.SomeInstance)
 
+UNTYPEDSTORAGE = lltype.GcStruct("untypedstorage",
+    ("shape", lltype.Ptr(STR)),
+    ("data", lltype.Array(llmemory.Address)),
+    rtti=True,
+)
+
+
+CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
+                                  llmemory.Address)
+def trace_untypedstorage(obj_addr, prev):
+    shape_addr = obj_addr + llmemory.offsetof(UNTYPEDSTORAGE, "shape")
+    if not prev:
+        return shape_addr
+    shape = shape_addr.address[0]
+    length_offset = (llmemory.offsetof(STR, "chars") +
+        llmemory.arraylengthoffset(STR.chars))
+    length = (shape + length_offset).signed[0]
+    if prev == shape_addr:
+        i = 0
+        while i < length:
+            char = (shape + llmemory.offsetof(STR, "chars") +
+                    llmemory.itemoffsetof(STR.chars, 0) +
+                    (llmemory.sizeof(STR.chars.OF) * i)).char[0]
+            if char == INSTANCE:
+                return (obj_addr + llmemory.offsetof(UNTYPEDSTORAGE, "data") +
+                        llmemory.itemoffsetof(UNTYPEDSTORAGE.data, 0) +
+                        llmemory.sizeof(UNTYPEDSTORAGE.data.OF) * i)
+            i += 1
+    return llmemory.NULL
+trace_untypedstorage_ptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), trace_untypedstorage)
+
 class UntypedStorageRepr(Repr):
-    lowleveltype = lltype.Ptr(lltype.GcStruct("untypedstorage",
-        ("shape", lltype.Ptr(rstr.STR)),
-        ("data", lltype.Array(lltype.Signed, hints={"nolength": True})),
-    ))
+    lowleveltype = lltype.Ptr(UNTYPEDSTORAGE)
+    lltype.attachRuntimeTypeInfo(lowleveltype.TO, customtraceptr=trace_untypedstorage_ptr)
 
     def _read_index(self, hop):
         v_arr = hop.inputarg(self, arg=0)
         c_name = hop.inputconst(lltype.Void, "data")
         hop.exception_cannot_occur()
         return hop.genop("getinteriorfield", [v_arr, c_name, v_idx],
-                         resulttype=lltype.Signed)
+                         resulttype=llmemory.Address)
 
     def _write_index(self, hop, v_value):
         v_arr = hop.inputarg(self, arg=0)
         hop.genop("setinteriorfield", [v_arr, c_name, v_idx, v_value])
 
     def rtyper_new(self, hop):
-        [v_shape] = hop.inputargs(rstr.string_repr)
+        [v_shape] = hop.inputargs(string_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_new, v_shape)
 
     def rtype_method_getint(self, hop):
-        return self._read_index(hop)
+        v_addr = self._read_index(hop)
+        return hop.genop("force_cast", [v_addr], resulttype=lltype.Signed)
 
     def rtype_method_setint(self, hop):
         v_value = hop.inputarg(lltype.Signed, arg=2)
-        self._write_index(hop, v_value)
+        v_addr = hop.genop("force_cast", [v_value], resulttype=llmemory.Address)
+        self._write_index(hop, v_addr)
 
     def rtype_method_getinstance(self, hop):
-        v_result = self._read_index(hop)
-        v_addr = hop.genop("cast_int_to_adr", [v_result], resulttype=llmemory.Address)
+        v_addr = self._read_index(hop)
         return hop.genop("cast_adr_to_ptr", [v_addr], resulttype=hop.r_result.lowleveltype)
 
     def rtype_method_setinstance(self, hop):
+        v_arr = hop.inputarg(self, arg=0)
         v_instance = hop.inputarg(hop.args_r[2], arg=2)
+        hop.genop("gc_writebarrier", [v_instance, v_arr])
 
         v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
                            resulttype=llmemory.Address)
-        v_value = hop.genop("cast_adr_to_int",
-                            [v_addr, hop.inputconst(lltype.Void, "symbolic")],
-                            resulttype=lltype.Signed)
-        self._write_index(hop, v_value)
+        self._write_index(hop, v_addr)
 
     @classmethod
     def ll_new(cls, shape):

File pypy/rpython/llinterp.py

View file
  • Ignore whitespace
         return ''.join(etype.name).rstrip('\x00')
     else:
         # ootype!
-        return etype._INSTANCE._name.split(".")[-1] 
+        return etype._INSTANCE._name.split(".")[-1]
 
 class LLInterpreter(object):
     """ low level interpreter working with concrete values. """
             return self.invoke_callable_with_pyexceptions(f, *args)
         args_v = graph.getargs()
         if len(ARGS) != len(args_v):
-            raise TypeError("graph with %d args called with wrong func ptr type: %r" %(len(args_v), ARGS)) 
+            raise TypeError("graph with %d args called with wrong func ptr type: %r" %(len(args_v), ARGS))
         for T, v in zip(ARGS, args_v):
             if not lltype.isCompatibleType(T, v.concretetype):
                 raise TypeError("graph with %r args called with wrong func ptr type: %r" %
-                                (tuple([v.concretetype for v in args_v]), ARGS)) 
+                                (tuple([v.concretetype for v in args_v]), ARGS))
         frame = self.newsubframe(graph, args)
         return frame.eval()
 
         if graphs is not None:
             obj = self.llinterpreter.typer.type_system.deref(f)
             if hasattr(obj, 'graph'):
-                assert obj.graph in graphs 
+                assert obj.graph in graphs
         else:
             pass
             #log.warn("op_indirect_call with graphs=None:", f)
     def op_zero_gc_pointers_inside(self, obj):
         raise NotImplementedError("zero_gc_pointers_inside")
 
+    def op_gc_writebarrier(self, newvalue, struct):
+        assert isinstance(lltype.typeOf(newvalue), lltype.Ptr)
+        assert isinstance(lltype.typeOf(struct), lltype.Ptr)
+        if hasattr(self.heap, "writebarrier"):
+            self.heap.writebarrier(newvalue, struct)
+
     def op_gc_writebarrier_before_copy(self, source, dest,
                                        source_start, dest_start, length):
         if hasattr(self.heap, 'writebarrier_before_copy'):
         return llmemory.raw_malloc_usage(size)
 
     def op_raw_free(self, addr):
-        checkadr(addr) 
+        checkadr(addr)
         llmemory.raw_free(addr)
 
     def op_raw_memclear(self, addr, size):
     def op_new(self, INST):
         assert isinstance(INST, (ootype.Instance, ootype.BuiltinType))
         return ootype.new(INST)
-        
+
     def op_oonewarray(self, ARRAY, length):
         assert isinstance(ARRAY, ootype.Array)
         assert isinstance(length, int)
         eq_name, interp_eq = \
                  wrap_callable(self.llinterpreter, eq_func, eq_obj, eq_method_name)
         EQ_FUNC = ootype.StaticMethod([DICT._KEYTYPE, DICT._KEYTYPE], ootype.Bool)
-        sm_eq = ootype.static_meth(EQ_FUNC, eq_name, _callable=interp_eq)        
+        sm_eq = ootype.static_meth(EQ_FUNC, eq_name, _callable=interp_eq)
 
         hash_name, interp_hash = \
                    wrap_callable(self.llinterpreter, hash_func, hash_obj, hash_method_name)

File pypy/rpython/lltypesystem/llmemory.py

View file
  • Ignore whitespace
 # sizeof, offsetof
 
 import weakref
-from pypy.rlib.objectmodel import Symbolic
+from pypy.rlib.objectmodel import Symbolic, specialize
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool.uid import uid
 
     else:
         raise Exception("don't know how to take the size of a %r"%TYPE)
 
+@specialize.arg(0)
 def sizeof(TYPE, n=None):
     if n is None:
         return _sizeof_none(TYPE)
         return itemoffsetof(TYPE) + _sizeof_none(TYPE.OF) * n
     else:
         return _sizeof_int(TYPE, n)
-sizeof._annspecialcase_ = 'specialize:arg(0)'
 
+@specialize.memo()
 def offsetof(TYPE, fldname):
     assert fldname in TYPE._flds
     return FieldOffset(TYPE, fldname)
-offsetof._annspecialcase_ = 'specialize:memo'
 
+@specialize.memo()
 def itemoffsetof(TYPE, n=0):
     result = ArrayItemsOffset(TYPE)
     if n != 0:
         result += ItemOffset(TYPE.OF) * n
     return result
-itemoffsetof._annspecialcase_ = 'specialize:memo'
+
+@specialize.memo()
+def arraylengthoffset(TYPE):
+    return ArrayLengthOffset(TYPE)
+
 # -------------------------------------------------------------
 
 class fakeaddress(object):
         assert isinstance(s_from, SomeAddress)
         assert isinstance(s_to, SomeAddress)
         assert isinstance(s_size, SomeInteger)
-    
+
     def specialize_call(self, hop):
         hop.exception_cannot_occur()
         v_list = hop.inputargs(Address, Address, lltype.Signed)

File pypy/rpython/lltypesystem/lloperation.py

View file
  • Ignore whitespace
     'gc_thread_before_fork':LLOp(),   # returns an opaque address
     'gc_thread_after_fork': LLOp(),   # arguments: (result_of_fork, opaqueaddr)
     'gc_assume_young_pointers': LLOp(canrun=True),
+    'gc_writebarrier': LLOp(canrun=True),
     'gc_writebarrier_before_copy': LLOp(canrun=True),
     'gc_heap_stats'       : LLOp(canmallocgc=True),
 

File pypy/rpython/memory/gcwrapper.py

View file
  • Ignore whitespace
         result = llmemory.cast_adr_to_ptr(addr, gctypelayout.WEAKREFPTR)
         result.weakptr = llmemory.cast_ptr_to_adr(objgetter())
         return llmemory.cast_ptr_to_weakrefptr(result)
-    
+
     def weakref_deref(self, PTRTYPE, obj):
         addr = gctypelayout.ll_weakref_deref(obj)
         return llmemory.cast_adr_to_ptr(addr, PTRTYPE)
         ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
         return self.gc.id(ptr)
 
+    def writebarrier(self, newvalue, struct):
+        if self.gc.needs_write_barrier:
+            newvalue_addr = llmemory.cast_ptr_to_adr(newvalue)
+            struct_addr = llmemory.cast_ptr_to_adr(struct)
+            self.gc.write_barrier(newvalue_addr, struct_addr)
+
     def writebarrier_before_copy(self, source, dest,
                                  source_start, dest_start, length):
         if self.gc.needs_write_barrier: