[pypy-commit] pypy op_malloc_gc: In-progress.

arigo noreply at buildbot.pypy.org
Sun Dec 18 15:51:48 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: op_malloc_gc
Changeset: r50654:2fd85080ac75
Date: 2011-12-18 15:06 +0100
http://bitbucket.org/pypy/pypy/changeset/2fd85080ac75/

Log:	In-progress.

diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -14,7 +14,7 @@
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD
-##from pypy.jit.backend.llsupport.descr import SizeDescr, ArrayDescr
+from pypy.jit.backend.llsupport.descr import SizeDescr, ArrayDescr
 from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
 from pypy.jit.backend.llsupport.descr import get_array_descr
 ##from pypy.jit.backend.llsupport.descr import GcPtrFieldDescr
@@ -70,30 +70,18 @@
     def gc_malloc(self, sizedescr):
         """Blackhole: do a 'bh_new'.  Also used for 'bh_new_with_vtable',
         with the vtable pointer set manually afterwards."""
-        assert isinstance(sizedescr, BaseSizeDescr)
-        return self._gc_malloc(sizedescr.size, sizedescr.tid)
+        assert isinstance(sizedescr, SizeDescr)
+        return self._bh_malloc(sizedescr)
 
     def gc_malloc_array(self, arraydescr, num_elem):
-        assert isinstance(arraydescr, BaseArrayDescr)
-        ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
-        basesize = arraydescr.get_base_size(self.translate_support_code)
-        itemsize = arraydescr.get_item_size(self.translate_support_code)
-        return self._gc_malloc_array(basesize, num_elem, itemsize, ofs_length,
-                                     arraydescr.tid)
+        assert isinstance(arraydescr, ArrayDescr)
+        return self._bh_malloc_array(arraydescr, num_elem)
 
     def gc_malloc_str(self, num_elem):
-        xxx
-        return self._gc_malloc_array(self.str_basesize, num_elem,
-                                     self.str_itemsize,
-                                     self.str_ofs_length,
-                                     self.str_type_id)
+        return self._bh_malloc_array(self.str_descr, num_elem)
 
     def gc_malloc_unicode(self, num_elem):
-        xxx
-        return self._gc_malloc_array(self.unicode_basesize, num_elem,
-                                     self.unicode_itemsize,
-                                     self.unicode_ofs_length,
-                                     self.unicode_type_id)
+        return self._bh_malloc_array(self.unicode_descr, num_elem)
 
     def _record_constptrs(self, op, gcrefs_output_list):
         for i in range(op.numargs()):
@@ -171,10 +159,9 @@
         self._make_functions()
 
     def _make_functions(self):
-        malloc_fn_ptr = self.malloc_fn_ptr
 
         def malloc_fixedsize(size):
-            res = malloc_fn_ptr(size)
+            res = self.malloc_fn_ptr(size)
             if not res:
                 raise MemoryError
             return res
@@ -182,12 +169,11 @@
                                [lltype.Signed])
 
         def malloc_array(basesize, num_elem, itemsize, ofs_length):
-            xxx
             try:
                 totalsize = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
             except OverflowError:
                 raise MemoryError
-            res = malloc_fn_ptr(totalsize)
+            res = self.malloc_fn_ptr(totalsize)
             if not res:
                 raise MemoryError
             arrayptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), res)
@@ -196,22 +182,13 @@
         self.generate_function('malloc_array', malloc_array,
                                [lltype.Signed] * 4)
 
-    def _gc_malloc(self, size, tid):
-        # Boehm: 'tid' is ignored
-        return self.malloc_fixedsize(size)
+    def _bh_malloc(self, sizedescr):
+        return self.malloc_fixedsize(sizedescr.size)
 
-    def _gc_malloc_array(self, basesize, num_elem, itemsize, ofs_length, tid):
-        # Boehm: 'tid' is ignored
-        try:
-            totalsize = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
-        except OverflowError:
-            raise MemoryError
-        res = self.malloc_fn_ptr(totalsize)
-        if not res:
-            raise MemoryError
-        arrayptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), res)
-        arrayptr[ofs_length/WORD] = num_elem
-        return res
+    def _bh_malloc_array(self, arraydescr, num_elem):
+        return self.malloc_array(arraydescr.basesize, num_elem,
+                                 arraydescr.itemsize,
+                                 arraydescr.lendescr.offset)
 
 
 # ____________________________________________________________
@@ -581,12 +558,14 @@
 
 class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
-        GCClass = gc_ll_descr.GCClass
         self.llop1 = gc_ll_descr.llop1
         self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR
         self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR
-        self.fielddescr_tid = get_field_descr(gc_ll_descr, GCClass.HDR, 'tid')
+        self.fielddescr_tid = gc_ll_descr.fielddescr_tid
         #
+        GCClass = gc_ll_descr.GCClass
+        if GCClass is None:     # for tests
+            return
         self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG
         self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = (
             self.extract_flag_byte(self.jit_wb_if_flag))
@@ -630,7 +609,6 @@
 
     def __init__(self, gcdescr, translator, rtyper, llop1=llop,
                  really_not_translated=False):
-        from pypy.rpython.memory.gctypelayout import check_typeid
         GcLLDescription.__init__(self, gcdescr, translator, rtyper)
         self.translator = translator
         self.llop1 = llop1
@@ -643,20 +621,16 @@
             self._make_gcrootmap()
             self._make_layoutbuilder()
             self._setup_gcclass()
+            self._setup_tid()
+        self._setup_write_barrier()
         self._setup_str()
-        self._setup_stuff(really_not_translated)
-        self._make_functions()
+        self._make_functions(really_not_translated)
 
     def _initialize_for_tests(self):
         self.layoutbuilder = None
         self.fielddescr_tid = AbstractDescr()
         self.max_size_of_young_obj = 1000
-        self.write_barrier_descr = None
-
-    def _setup_stuff(self, really_not_translated):
-        (self.standard_array_basesize, _, self.standard_array_length_ofs) = \
-             symbolic.get_array_token(lltype.GcArray(lltype.Signed),
-                                      not really_not_translated)
+        self.GCClass = None
 
     def _check_valid_gc(self):
         # we need the hybrid or minimark GC for rgc._make_sure_does_not_move()
@@ -699,8 +673,22 @@
         assert self.GCClass.inline_simple_malloc
         assert self.GCClass.inline_simple_malloc_varsize
 
-    def _make_functions(self):
+    def _setup_tid(self):
+        self.fielddescr_tid = get_field_descr(self, self.GCClass.HDR, 'tid')
+
+    def _setup_write_barrier(self):
+        self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
+            [llmemory.Address, llmemory.Address], lltype.Void))
+        self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType(
+            [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void))
+        self.write_barrier_descr = WriteBarrierDescr(self)
+
+    def _make_functions(self, really_not_translated):
+        from pypy.rpython.memory.gctypelayout import check_typeid
         llop1 = self.llop1
+        (self.standard_array_basesize, _, self.standard_array_length_ofs) = \
+             symbolic.get_array_token(lltype.GcArray(lltype.Signed),
+                                      not really_not_translated)
 
         def malloc_nursery_slowpath(size):
             """Allocate 'size' null bytes out of the nursery.
@@ -762,73 +750,26 @@
         self.generate_function('malloc_fixedsize', malloc_nursery_slowpath,
                                [lltype.Signed])
 
-##        # make the fixed malloc function, with one argument
-##        def malloc_gc_fixed(size):
-##            type_id = rffi.cast(llgroup.HALFWORD, 0)    # missing here
-##            res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
-##                                                  type_id, size,
-##                                                  False, False, False)
-##            #llop.debug_print(lltype.Void, "\tmalloc_basic", size, "-->", res)
-##            # In case the operation above failed, we are returning NULL
-##            # from this function to assembler.  There is also an RPython
-##            # exception set, typically MemoryError; but it's easier and
-##            # faster to check for the NULL return value, as done by
-##            # translator/exceptiontransform.py.
-##            return res
-##        self.malloc_gc_fixed = malloc_gc_fixed
-##        self.MALLOC_GC_FIXED = lltype.Ptr(
-##            lltype.FuncType([lltype.Signed], llmemory.GCREF))
-##        #
-##        # make the varsize malloc function, with three arguments
-##        def malloc_gc_variable(basesize, num_elem, itemsize):
-##            xx
-##        self.malloc_gc_variable = malloc_gc_variable
-##        self.MALLOC_GC_VARIABLE = lltype.Ptr(
-##            lltype.FuncType([lltype.Signed] * 3, llmemory.GCREF))
-##        #
-##        self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
-##            [llmemory.Address, llmemory.Address], lltype.Void))
-##        self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType(
-##            [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void))
-##        self.write_barrier_descr = WriteBarrierDescr(self)
-##        self.fielddescr_tid = self.write_barrier_descr.fielddescr_tid
-##        #
-##        (str_basesize, str_itemsize, str_ofs_length
-##         ) = symbolic.get_array_token(rstr.STR, True)
-##        (unicode_basesize, unicode_itemsize, unicode_ofs_length
-##         ) = symbolic.get_array_token(rstr.UNICODE, True)
-##        self.str_type_id = self.layoutbuilder.get_type_id(rstr.STR)
-##        self.unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE)
-##        #
-##        def malloc_str(length):
-##            return llop1.do_malloc_varsize_clear(
-##                llmemory.GCREF,
-##                str_type_id, length, str_basesize, str_itemsize,
-##                str_ofs_length)
-##        def malloc_unicode(length):
-##            return llop1.do_malloc_varsize_clear(
-##                llmemory.GCREF,
-##                unicode_type_id, length, unicode_basesize,unicode_itemsize,
-##                unicode_ofs_length)
-##        ###self.malloc_str = malloc_str
-##        ###self.malloc_unicode = malloc_unicode
-##        ###self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(
-##        ###    [lltype.Signed], llmemory.GCREF))
-##        #
-##        #
-##        def malloc_slowpath(size):
-##            if self.DEBUG:
-##                random_usage_of_xmm_registers()
-##            assert size >= self.minimal_size_in_nursery
-##            # NB. although we call do_malloc_fixedsize_clear() here,
-##            # it's a bit of a hack because we set tid to 0 and may
-##            # also use it to allocate varsized objects.  The tid
-##            # and possibly the length are both set afterward.
-##            gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
-##                                        0, size, False, False, False)
-##            return rffi.cast(lltype.Signed, gcref)
-##        self.malloc_slowpath = malloc_slowpath
-##        self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
+    def _bh_malloc(self, sizedescr):
+        from pypy.rpython.memory.gctypelayout import check_typeid
+        llop1 = self.llop1
+        type_id = llop.extract_ushort(llgroup.HALFWORD, sizedescr.tid)
+        check_typeid(type_id)
+        return llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
+                                               type_id, sizedescr.size,
+                                               False, False, False)
+
+    def _bh_malloc_array(self, arraydescr, num_elem):
+        from pypy.rpython.memory.gctypelayout import check_typeid
+        llop1 = self.llop1
+        type_id = llop.extract_ushort(llgroup.HALFWORD, arraydescr.tid)
+        check_typeid(type_id)
+        return llop1.do_malloc_varsize_clear(llmemory.GCREF,
+                                             type_id, num_elem,
+                                             arraydescr.basesize,
+                                             arraydescr.itemsize,
+                                             arraydescr.lendescr.offset)
+
 
     class ForTestOnly:
         pass
@@ -842,14 +783,6 @@
         x3 = x0 * 0.3
         self.for_test_only.x = x0 + x1 + x2 + x3
 
-    def get_funcptr_for_malloc_gc_fixed(self):
-        """(size) -> GCREF"""
-        return llhelper(self.MALLOC_GC_FIXED, self.malloc_gc_fixed)
-
-    def get_funcptr_for_malloc_gc_variable(self):
-        """(base_size, num_elem, item_size) -> GCREF"""
-        return llhelper(self.MALLOC_GC_VARIABLE, self.malloc_gc_variable)
-
     def get_nursery_free_addr(self):
         nurs_addr = llop.gc_adr_of_nursery_free(llmemory.Address)
         return rffi.cast(lltype.Signed, nurs_addr)
diff --git a/pypy/jit/backend/llsupport/rewrite.py b/pypy/jit/backend/llsupport/rewrite.py
--- a/pypy/jit/backend/llsupport/rewrite.py
+++ b/pypy/jit/backend/llsupport/rewrite.py
@@ -1,5 +1,5 @@
 from pypy.rlib.rarithmetic import ovfcheck
-from pypy.jit.metainterp.history import ConstInt
+from pypy.jit.metainterp.history import ConstInt, BoxPtr, ConstPtr
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.codewriter import heaptracker
 from pypy.jit.backend.llsupport.symbolic import WORD
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -32,8 +32,8 @@
     A = lltype.GcArray(lltype.Signed)
     arraydescr = get_array_descr(gc_ll_descr, A)
     p = gc_ll_descr.gc_malloc_array(arraydescr, 10)
-    assert record == [(arraydescr.get_base_size(False) +
-                       10 * arraydescr.get_item_size(False), p)]
+    assert record == [(arraydescr.basesize +
+                       10 * arraydescr.itemsize, p)]
     del record[:]
     # ---------- gc_malloc_str ----------
     p = gc_ll_descr.gc_malloc_str(10)
@@ -246,47 +246,50 @@
     def __init__(self):
         self.record = []
 
+    def _malloc(self, type_id, size):
+        tid = llop.combine_ushort(lltype.Signed, type_id, 0)
+        x = llmemory.raw_malloc(self.gcheaderbuilder.size_gc_header + size)
+        x += self.gcheaderbuilder.size_gc_header
+        return x, tid
+
     def do_malloc_fixedsize_clear(self, RESTYPE, type_id, size,
                                   has_finalizer, has_light_finalizer,
                                   contains_weakptr):
         assert not contains_weakptr
         assert not has_finalizer
         assert not has_light_finalizer
-        assert rffi.cast(lltype.Signed, type_id) == 0
-        x = llmemory.raw_malloc(self.gcheaderbuilder.size_gc_header + size)
-        x += self.gcheaderbuilder.size_gc_header
-        p = llmemory.cast_adr_to_ptr(x, RESTYPE)
-        self.record.append(("fixedsize", repr(size), p))
+        p, tid = self._malloc(type_id, size)
+        p = llmemory.cast_adr_to_ptr(p, RESTYPE)
+        self.record.append(("fixedsize", repr(size), tid, p))
         return p
 
-##    def do_malloc_varsize_clear(self, RESTYPE, type_id, length, size,
-##                                itemsize, offset_to_length):
-##        p = llmemory.raw_malloc(size + itemsize * length)
-##        (p + offset_to_length).signed[0] = length
-##        p = llmemory.cast_adr_to_ptr(p, RESTYPE)
-##        tid = llop.combine_ushort(lltype.Signed, type_id, 0)
-##        self.record.append(("varsize", tid, length,
-##                            repr(size), repr(itemsize),
-##                            repr(offset_to_length), p))
-##        return p
+    def do_malloc_varsize_clear(self, RESTYPE, type_id, length, size,
+                                itemsize, offset_to_length):
+        p, tid = self._malloc(type_id, size + itemsize * length)
+        (p + offset_to_length).signed[0] = length
+        p = llmemory.cast_adr_to_ptr(p, RESTYPE)
+        self.record.append(("varsize", tid, length,
+                            repr(size), repr(itemsize),
+                            repr(offset_to_length), p))
+        return p
 
-##    def _write_barrier_failing_case(self, adr_struct, adr_newptr):
-##        self.record.append(('barrier', adr_struct, adr_newptr))
+    def _write_barrier_failing_case(self, adr_struct, adr_newptr):
+        self.record.append(('barrier', adr_struct, adr_newptr))
 
-##    def get_write_barrier_failing_case(self, FPTRTYPE):
-##        return llhelper(FPTRTYPE, self._write_barrier_failing_case)
+    def get_write_barrier_failing_case(self, FPTRTYPE):
+        return llhelper(FPTRTYPE, self._write_barrier_failing_case)
 
-##    _have_wb_from_array = False
+    _have_wb_from_array = False
 
-##    def _write_barrier_from_array_failing_case(self, adr_struct, v_index):
-##        self.record.append(('barrier_from_array', adr_struct, v_index))
+    def _write_barrier_from_array_failing_case(self, adr_struct, v_index):
+        self.record.append(('barrier_from_array', adr_struct, v_index))
 
-##    def get_write_barrier_from_array_failing_case(self, FPTRTYPE):
-##        if self._have_wb_from_array:
-##            return llhelper(FPTRTYPE,
-##                            self._write_barrier_from_array_failing_case)
-##        else:
-##            return lltype.nullptr(FPTRTYPE.TO)
+    def get_write_barrier_from_array_failing_case(self, FPTRTYPE):
+        if self._have_wb_from_array:
+            return llhelper(FPTRTYPE,
+                            self._write_barrier_from_array_failing_case)
+        else:
+            return lltype.nullptr(FPTRTYPE.TO)
 
 
 class TestFramework(object):
@@ -345,22 +348,18 @@
         sizedescr = get_size_descr(self.gc_ll_descr, S)
         p = self.gc_ll_descr.gc_malloc(sizedescr)
         assert lltype.typeOf(p) == llmemory.GCREF
-        assert self.llop1.record == [("fixedsize", repr(sizedescr.size), p)]
-        p1 = lltype.cast_opaque_ptr(lltype.Ptr(S), p)
-        hdr = self.gc_ll_descr.gcheaderbuilder.header_of_object(p1)
-        assert hdr.tid == sizedescr.tid
+        assert self.llop1.record == [("fixedsize", repr(sizedescr.size),
+                                      sizedescr.tid, p)]
 
     def test_gc_malloc_array(self):
         A = lltype.GcArray(lltype.Signed)
         arraydescr = get_array_descr(self.gc_ll_descr, A)
         p = self.gc_ll_descr.gc_malloc_array(arraydescr, 10)
         assert self.llop1.record == [("varsize", arraydescr.tid, 10,
-                                      repr(arraydescr.get_base_size(True)),
-                                      repr(arraydescr.get_item_size(True)),
-                                      repr(arraydescr.get_ofs_length(True)),
+                                      repr(arraydescr.basesize),
+                                      repr(arraydescr.itemsize),
+                                      repr(arraydescr.lendescr.offset),
                                       p)]
-        assert repr(self.gc_ll_descr.args_for_new_array(arraydescr)) == repr(
-            [arraydescr.get_item_size(True), arraydescr.tid])
 
     def test_gc_malloc_str(self):
         p = self.gc_ll_descr.gc_malloc_str(10)
@@ -430,8 +429,7 @@
         operations = gc_ll_descr.rewrite_assembler(None, operations, [])
         assert len(operations) == 0
 
-    def test_rewrite_assembler_1(self):
-        # check recording of ConstPtrs
+    def test_record_constptrs(self):
         class MyFakeCPU(object):
             def cast_adr_to_int(self, adr):
                 assert adr == "some fake address"
@@ -552,8 +550,7 @@
     def test_rewrite_assembler_5(self):
         S = lltype.GcStruct('S')
         A = lltype.GcArray(lltype.Struct('A', ('x', lltype.Ptr(S))))
-        interiordescr = get_interiorfield_descr(self.gc_ll_descr, A,
-                                                A.OF, 'x')
+        interiordescr = get_interiorfield_descr(self.gc_ll_descr, A, 'x')
         wbdescr = self.gc_ll_descr.write_barrier_descr
         ops = parse("""
         [p1, p2]
@@ -572,19 +569,18 @@
         equaloplists(operations, expected.operations)
 
     def test_rewrite_assembler_initialization_store(self):
-        S = lltype.GcStruct('S', ('parent', OBJECT),
-                            ('x', lltype.Signed))
-        s_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+        sdescr = get_size_descr(self.gc_ll_descr, S)
         xdescr = get_field_descr(self.gc_ll_descr, S, 'x')
         ops = parse("""
         [p1]
-        p0 = new_with_vtable(ConstClass(s_vtable))
+        p0 = new(descr=sdescr)
         setfield_gc(p0, p1, descr=xdescr)
         jump()
         """, namespace=locals())
         expected = parse("""
         [p1]
-        p0 = new_with_vtable(ConstClass(s_vtable))
+        p0 = new(descr=sdescr)
         # no write barrier
         setfield_gc(p0, p1, descr=xdescr)
         jump()
diff --git a/pypy/jit/backend/llsupport/test/test_rewrite.py b/pypy/jit/backend/llsupport/test/test_rewrite.py
--- a/pypy/jit/backend/llsupport/test/test_rewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_rewrite.py
@@ -21,10 +21,11 @@
         sdescr.tid = 1234
         #
         T = lltype.GcStruct('T', ('y', lltype.Signed),
-                                 ('z', lltype.Signed),
+                                 ('z', lltype.Ptr(S)),
                                  ('t', lltype.Signed))
         tdescr = get_size_descr(self.gc_ll_descr, T)
         tdescr.tid = 5678
+        tzdescr = get_field_descr(self.gc_ll_descr, T, 'z')
         #
         A = lltype.GcArray(lltype.Signed)
         adescr = get_array_descr(self.gc_ll_descr, A)
@@ -47,6 +48,7 @@
         register_known_gctype(self.cpu, o_vtable, O)
         #
         tiddescr = self.gc_ll_descr.fielddescr_tid
+        wbdescr = self.gc_ll_descr.write_barrier_descr
         WORD = globals()['WORD']
         #
         strdescr     = self.gc_ll_descr.str_descr
@@ -409,3 +411,15 @@
             p3 = call_malloc_gc(ConstClass(malloc_str), i2)
             jump()
         """)
+
+    def test_write_barrier_before_setfield_gc(self):
+        self.check_rewrite("""
+            [p1, p2]
+            setfield_gc(p1, p2, descr=tzdescr)
+            jump()
+        """, """
+            [p1, p2]
+            cond_call_gc_wb(p1, p2, descr=wbdescr)
+            setfield_raw(p1, p2, descr=tzdescr)
+            jump()
+        """)


More information about the pypy-commit mailing list