Author: Maciej Fijalkowski <[email protected]>
Branch: fast-newarray
Changeset: r62381:02b837da85cc
Date: 2013-03-17 09:46 -0700
http://bitbucket.org/pypy/pypy/changeset/02b837da85cc/

Log:    (exarkun, fijal) Make rewrite emit a new operation called
        malloc_nursery_varsize

diff --git a/rpython/jit/backend/llsupport/rewrite.py 
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -9,18 +9,24 @@
 from rpython.jit.metainterp.history import JitCellToken
 
 class GcRewriterAssembler(object):
-    # This class performs the following rewrites on the list of operations:
-    #
-    # - Remove the DEBUG_MERGE_POINTs.
-    #
-    # - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY
-    #   followed by SETFIELDs in order to initialize their GC fields.  The
-    #   two advantages of CALL_MALLOC_NURSERY is that it inlines the common
-    #   path, and we need only one such operation to allocate several blocks
-    #   of memory at once.
-    #
-    # - Add COND_CALLs to the write barrier before SETFIELD_GC and
-    #   SETARRAYITEM_GC operations.
+    """ This class performs the following rewrites on the list of operations:
+
+     - Remove the DEBUG_MERGE_POINTs.
+
+     - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY
+       followed by SETFIELDs in order to initialize their GC fields.  The
+       two advantages of CALL_MALLOC_NURSERY is that it inlines the common
+       path, and we need only one such operation to allocate several blocks
+       of memory at once.
+
+     - Add COND_CALLs to the write barrier before SETFIELD_GC and
+       SETARRAYITEM_GC operations.
+
+    recent_mallocs contains a dictionary of variable -> None. If a variable
+    is in the dictionary, next setfields can be called without a write barrier,
+    because the variable got allocated after the last potentially collecting
+    resop
+    """
 
     _previous_size = -1
     _op_malloc_nursery = None
@@ -32,7 +38,7 @@
         self.cpu = cpu
         self.newops = []
         self.known_lengths = {}
-        self.recent_mallocs = {}     # set of variables
+        self.recent_mallocs = {}
 
     def rewrite(self, operations):
         # we can only remember one malloc since the next malloc can possibly
@@ -119,6 +125,12 @@
                 pass    # total_size is still -1
         elif arraydescr.itemsize == 0:
             total_size = arraydescr.basesize
+        elif (self.gc_ll_descr.can_use_nursery_malloc(1) and
+              self.gen_malloc_nursery_varsize(arraydescr.itemsize,
+              v_length, op.result, arraydescr)):
+            self.gen_initialize_tid(op.result, arraydescr.tid)
+            self.gen_initialize_len(op.result, v_length, arraydescr.lendescr)
+            return
         if (total_size >= 0 and
                 self.gen_malloc_nursery(total_size, op.result)):
             self.gen_initialize_tid(op.result, arraydescr.tid)
@@ -152,7 +164,7 @@
                                size_box,
                                descr=descrs.jfi_frame_size)
             self.newops.append(op0)
-            self.gen_malloc_nursery_varsize(size_box, frame, is_small=True)
+            self.gen_malloc_nursery_varsize_small(size_box, frame)
             self.gen_initialize_tid(frame, descrs.arraydescr.tid)
             length_box = history.BoxInt()
             op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)],
@@ -281,10 +293,25 @@
         self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result,
                                  self.gc_ll_descr.malloc_unicode_descr)
 
-    def gen_malloc_nursery_varsize(self, sizebox, v_result, is_small=False):
+    def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result,
+                                   arraydescr):
+        """ itemsize is an int, v_length and v_result are boxes
+        """
+        if (arraydescr.basesize != self.gc_ll_descr.standard_array_basesize
+            or arraydescr.lendescr.offset !=
+            self.gc_ll_descr.standard_array_length_ofs):
+            return False
+        self.emitting_an_operation_that_can_collect()
+        op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE,
+                          [ConstInt(itemsize), v_length],
+                          v_result)
+        self.newops.append(op)
+        self.recent_mallocs[v_result] = None
+        return True
+
+    def gen_malloc_nursery_varsize_small(self, sizebox, v_result):
         """ Generate CALL_MALLOC_NURSERY_VARSIZE_SMALL
         """
-        assert is_small
         self.emitting_an_operation_that_can_collect()
         op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL,
                           [sizebox],
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py 
b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -85,6 +85,7 @@
         signedframedescr = self.cpu.signedframedescr
         floatframedescr = self.cpu.floatframedescr
         casmdescr.compiled_loop_token = clt
+        tzdescr = None # noone cares
         #
         namespace.update(locals())
         #
@@ -107,7 +108,7 @@
 
 class BaseFakeCPU(object):
     JITFRAME_FIXED_SIZE = 0
-    
+
     def __init__(self):
         self.tracker = FakeTracker()
         self._cache = {}
@@ -121,7 +122,7 @@
 
     def unpack_arraydescr_size(self, d):
         return 0, d.itemsize, 0
-    
+
     def arraydescrof(self, ARRAY):
         try:
             return self._cache[ARRAY]
@@ -129,7 +130,7 @@
             r = ArrayDescr(1, 2, FieldDescr('len', 0, 0, 0), 0)
             self._cache[ARRAY] = r
             return r
-        
+
     def fielddescrof(self, STRUCT, fname):
         key = (STRUCT, fname)
         try:
@@ -407,9 +408,9 @@
             jump(i0)
         """, """
             [i0]
-            p0 = call_malloc_gc(ConstClass(malloc_array), 1,  \
-                                %(bdescr.tid)d, i0,           \
-                                descr=malloc_array_descr)
+            p0 = call_malloc_nursery_varsize(1, i0)
+            setfield_gc(p0, %(bdescr.tid)d, descr=tiddescr)
+            setfield_gc(p0, i0, descr=blendescr)
             jump(i0)
         """)
 
diff --git a/rpython/jit/metainterp/executor.py 
b/rpython/jit/metainterp/executor.py
--- a/rpython/jit/metainterp/executor.py
+++ b/rpython/jit/metainterp/executor.py
@@ -354,6 +354,7 @@
                          rop.QUASIIMMUT_FIELD,
                          rop.CALL_MALLOC_GC,
                          rop.CALL_MALLOC_NURSERY,
+                         rop.CALL_MALLOC_NURSERY_VARSIZE,
                          rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL,
                          rop.LABEL,
                          ):      # list of opcodes never executed by pyjitpl
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -529,6 +529,7 @@
     'CALL_PURE/*d',             # removed before it's passed to the backend
     'CALL_MALLOC_GC/*d',      # like CALL, but NULL => propagate MemoryError
     'CALL_MALLOC_NURSERY/1',  # nursery malloc, const number of bytes, zeroed
+    'CALL_MALLOC_NURSERY_VARSIZE/2',
     'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1',
     # nursery malloc, non-const number of bytes, zeroed
     # note that the number of bytes must be well known to be small enough
diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py
--- a/rpython/jit/tool/oparser.py
+++ b/rpython/jit/tool/oparser.py
@@ -106,6 +106,8 @@
                 tt = self.model.TargetToken(token)
                 self._consts[poss_descr] = tt
                 return tt
+            else:
+                raise
 
     def box_for_var(self, elem):
         try:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to