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