Author: fijal
Branch: copystrcontents-in-rewrite
Changeset: r96731:825a9d694c31
Date: 2019-06-04 12:48 +0200
http://bitbucket.org/pypy/pypy/changeset/825a9d694c31/
Log: an attempt to rewrite copystr/copyunicode content
diff --git a/rpython/jit/backend/llsupport/gc.py
b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -14,6 +14,7 @@
from rpython.jit.metainterp.support import ptr2int
from rpython.jit.backend.llsupport import symbolic, jitframe
from rpython.jit.backend.llsupport.symbolic import WORD
+from rpython.jit.backend.llsupport.memcpy import memcpy_fn
from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr,
FieldDescr
from rpython.jit.backend.llsupport.descr import GcCache, get_field_descr
from rpython.jit.backend.llsupport.descr import get_array_descr
@@ -36,6 +37,11 @@
self.fielddescr_vtable = get_field_descr(self, rclass.OBJECT,
'typeptr')
self._generated_functions = []
+ self.memcpy_fn = memcpy_fn
+ self.memcpy_descr = get_call_descr(self,
+ [lltype.Signed, lltype.Signed, lltype.Signed], lltype.Void,
+ EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+ can_collect=False))
def _setup_str(self):
self.str_descr = get_array_descr(self, rstr.STR)
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
@@ -34,6 +34,10 @@
- Add COND_CALLs to the write barrier before SETFIELD_GC and
SETARRAYITEM_GC operations.
+ - Rewrites copystrcontent to a call to memcopy
+
+ - XXX does more than that, please write it down
+
'_write_barrier_applied' contains a dictionary of variable -> None.
If a variable is in the dictionary, next setfields can be called without
a write barrier. The idea is that an object that was freshly allocated
@@ -335,6 +339,10 @@
self.emitting_an_operation_that_can_collect()
elif op.getopnum() == rop.LABEL:
self.emit_label()
+ # ---- change COPY{STR|UNICODE}CONTENT into a call ------
+ if op.opnum == rop.COPYSTRCONTENT or op.opnum ==
rop.COPYUNICODECONTENT:
+ self.rewrite_copy_str_content(op)
+ continue
# ---------- write barriers ----------
if self.gc_ll_descr.write_barrier_descr is not None:
if op.getopnum() == rop.SETFIELD_GC:
@@ -953,6 +961,46 @@
self.gcrefs_output_list.append(gcref)
return index
+ def rewrite_copy_str_content(self, op):
+ funcaddr = llmemory.cast_ptr_to_adr(self.gc_ll_descr.memcpy_fn)
+ memcpy_fn = self.cpu.cast_adr_to_int(funcaddr)
+ memcpy_descr = self.gc_ll_descr.memcpy_descr
+ if op.getopnum() == rop.COPYSTRCONTENT:
+ basesize = self.gc_ll_descr.str_descr.basesize
+ # because we have one extra item after alloc, the actual address
+ # of string start is 1 lower, from extra_item_after_malloc
+ base = ConstInt(basesize - 1)
+ itemsize = self.gc_ll_descr.str_descr.itemsize
+ assert itemsize == 1
+ itemscale = ConstInt(0)
+ else:
+ base = ConstInt(self.gc_ll_descr.unicode_descr.basesize)
+ itemsize = self.gc_ll_descr.unicode_descr.itemsize
+ if itemsize == 2:
+ itemscale = ConstInt(1)
+ elif itemsize == 4:
+ itemscale = ConstInt(2)
+ else:
+ assert False, "unknown size of unicode"
+ i1 = ResOperation(rop.LOAD_EFFECTIVE_ADDRESS,
+ [op.getarg(0), op.getarg(2), base, itemscale])
+ i2 = ResOperation(rop.LOAD_EFFECTIVE_ADDRESS,
+ [op.getarg(1), op.getarg(3), base, itemscale])
+ self.emit_op(i1)
+ self.emit_op(i2)
+ if op.getopnum() == rop.COPYSTRCONTENT:
+ arg = op.getarg(4)
+ else:
+ # do some basic constant folding
+ if isinstance(op.getarg(4), ConstInt):
+ arg = ConstInt(op.getarg(4).getint() * itemsize)
+ else:
+ arg = ResOperation(rop.INT_MUL, [op.getarg(4),
ConstInt(itemsize)])
+ self.emit_op(arg)
+ self.emit_op(ResOperation(rop.CALL_N,
+ [ConstInt(memcpy_fn), i2, i1, arg], descr=memcpy_descr))
+
+
def remove_constptr(self, c):
"""Remove all ConstPtrs, and replace them with load_from_gc_table.
"""
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
@@ -147,6 +147,8 @@
unicodelendescr = unicodedescr.lendescr
strhashdescr = self.gc_ll_descr.str_hash_descr
unicodehashdescr = self.gc_ll_descr.unicode_hash_descr
+ memcpy_fn = self.gc_ll_descr.memcpy_fn
+ memcpy_descr = self.gc_ll_descr.memcpy_descr
casmdescr = JitCellToken()
clt = FakeLoopToken()
@@ -169,6 +171,7 @@
signedframedescr = self.cpu.signedframedescr
floatframedescr = self.cpu.floatframedescr
casmdescr.compiled_loop_token = clt
+
#
guarddescr = AbstractFailDescr()
#
@@ -237,6 +240,9 @@
self._cache[key] = r
return r
+ def cast_adr_to_int(self, adr):
+ return rffi.cast(lltype.Signed, adr)
+
class TestBoehm(RewriteTests):
def setup_method(self, meth):
class FakeCPU(BaseFakeCPU):
@@ -1436,3 +1442,14 @@
jump()
""")
assert len(self.gcrefs) == 2
+
+ def test_rewrite_copystrcontents(self):
+ self.check_rewrite("""
+ [p0, p1, i0, i1, i_len]
+ copystrcontent(p0, p1, i0, i1, i_len)
+ """, """
+ [p0, p1, i0, i1, i_len]
+ i2 = load_effective_address(p0, i0, %(strdescr.basesize)s,
%(strdescr.itemsize)s)
+ i3 = load_effective_address(p1, i1, %(strdescr.basesize)s,
%(strdescr.itemsize)s)
+ call_n(ConstClass(memcpy_fn), i2, i3, i_len, descr=memcpy_descr)
+ """)
diff --git a/rpython/jit/backend/x86/regalloc.py
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -1222,6 +1222,17 @@
resloc = self.force_allocate_reg(op, [op.getarg(0)])
self.perform(op, [argloc], resloc)
+ def consider_load_effective_address(self, op):
+ p0 = op.getarg(0)
+ i0 = op.getarg(1)
+ ploc = self.make_sure_var_in_reg(p0, [i0])
+ iloc = self.make_sure_var_in_reg(i0, [p0])
+ res = self.rm.force_allocate_reg(op, [p0, i0])
+ assert isinstance(op.getarg(2), ConstInt)
+ assert isinstance(op.getarg(3), ConstInt)
+ self.assembler.load_effective_addr(iloc, op.getarg(2).getint(),
+ op.getarg(3).getint(), res, ploc)
+
def consider_copystrcontent(self, op):
self._consider_copystrcontent(op, is_unicode=False)
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
@@ -441,6 +441,7 @@
rop.GC_STORE,
rop.GC_STORE_INDEXED,
rop.LOAD_FROM_GC_TABLE,
+ rop.LOAD_EFFECTIVE_ADDRESS,
): # list of opcodes never executed by pyjitpl
continue
if rop._VEC_PURE_FIRST <= value <= rop._VEC_PURE_LAST:
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
@@ -1056,6 +1056,8 @@
#
'LOAD_FROM_GC_TABLE/1/r', # only emitted by rewrite.py
#
+ 'LOAD_EFFECTIVE_ADDRESS/4/i', # only emitted by rewrite.py, shortcut for
x86
+ #
'_ALWAYS_PURE_LAST', # ----- end of always_pure operations -----
# parameters GC_LOAD
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit