[pypy-commit] pypy stm-jit: Starting on stmrewrite.py.
arigo
noreply at buildbot.pypy.org
Fri Aug 10 15:46:22 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-jit
Changeset: r56695:14d1f61b2e13
Date: 2012-08-10 15:45 +0200
http://bitbucket.org/pypy/pypy/changeset/14d1f61b2e13/
Log: Starting on stmrewrite.py.
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
@@ -106,7 +106,7 @@
from pypy.jit.backend.llsupport.rewrite import GcRewriterAssembler
else:
from pypy.jit.backend.llsupport import stmrewrite
- GcRewriterAssembler = stmrewrite.GcStmReviewerAssembler
+ GcRewriterAssembler = stmrewrite.GcStmRewriterAssembler
rewriter = GcRewriterAssembler(self, cpu)
newops = rewriter.rewrite(operations)
# record all GCREFs, because the GC (or Boehm) cannot see them and
@@ -683,7 +683,10 @@
def _initialize_for_tests(self):
self.layoutbuilder = None
self.fielddescr_tid = AbstractDescr()
- self.max_size_of_young_obj = 1000
+ if self.stm:
+ self.max_size_of_young_obj = None
+ else:
+ self.max_size_of_young_obj = 1000
self.GCClass = None
def _check_valid_gc(self):
@@ -893,7 +896,7 @@
funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
def can_use_nursery_malloc(self, size):
- return (self.max_size_of_young_obj is None or
+ return (self.max_size_of_young_obj is not None and
size < self.max_size_of_young_obj)
def has_write_barrier_class(self):
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
@@ -31,7 +31,7 @@
self.cpu = cpu
self.newops = []
self.known_lengths = {}
- self.recent_mallocs = {} # set of variables
+ self.recent_mallocs = set() # set of variables
def rewrite(self, operations):
# we can only remember one malloc since the next malloc can possibly
@@ -47,7 +47,7 @@
if op.is_malloc():
self.handle_malloc_operation(op)
continue
- elif op.can_malloc():
+ elif op.is_call():
self.emitting_an_operation_that_can_collect()
elif op.getopnum() == rop.LABEL:
self.emitting_an_operation_that_can_collect()
@@ -147,7 +147,7 @@
op = ResOperation(rop.CALL_MALLOC_GC, args, v_result, descr)
self.newops.append(op)
# mark 'v_result' as freshly malloced
- self.recent_mallocs[v_result] = None
+ self.recent_mallocs.add(v_result)
def gen_malloc_fixedsize(self, size, typeid, v_result):
"""Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, ...).
@@ -247,7 +247,7 @@
self.newops.append(op)
self._previous_size = size
self._v_last_malloced_nursery = v_result
- self.recent_mallocs[v_result] = None
+ self.recent_mallocs.add(v_result)
return True
def gen_initialize_tid(self, v_newgcobj, tid):
diff --git a/pypy/jit/backend/llsupport/stmrewrite.py b/pypy/jit/backend/llsupport/stmrewrite.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/llsupport/stmrewrite.py
@@ -0,0 +1,63 @@
+from pypy.jit.backend.llsupport.rewrite import GcRewriterAssembler
+from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.history import BoxPtr, ConstPtr
+
+
+class GcStmRewriterAssembler(GcRewriterAssembler):
+ # This class performs the same rewrites as its base class,
+ # plus the rewrites described in stm.txt.
+
+ def __init__(self, *args):
+ GcRewriterAssembler.__init__(self, *args)
+ self.known_local = set() # set of variables
+
+ def rewrite(self, operations):
+ # overridden method from parent class
+ #
+ for op in operations:
+ if op.getopnum() == rop.DEBUG_MERGE_POINT:
+ continue
+ # ---------- mallocs ----------
+ if op.is_malloc():
+ self.handle_malloc_operation(op)
+ continue
+ # ---------- setfields ----------
+ if op.getopnum() in (rop.SETFIELD_GC,
+ rop.SETARRAYITEM_GC,
+ rop.SETINTERIORFIELD_GC):
+ self.handle_write_barrier(op)
+ continue
+ # ---------- calls, labels ----------
+ if op.is_call() or op.getopnum() == rop.LABEL:
+ self.known_local.clear()
+ # ----------
+ self.newops.append(op)
+ return self.newops
+
+
+ def gen_write_barrier(self, v_base):
+ assert isinstance(v_base, BoxPtr)
+ if v_base in self.known_local:
+ return # no write barrier needed
+ write_barrier_descr = self.gc_ll_descr.write_barrier_descr
+ args = [v_base, self.c_zero]
+ self.newops.append(ResOperation(rop.COND_CALL_GC_WB, args, None,
+ descr=write_barrier_descr))
+ self.known_local.add(v_base)
+
+ def unconstifyptr(self, v):
+ if isinstance(v, ConstPtr):
+ v_in = v
+ v_out = BoxPtr()
+ self.newops.append(ResOperation(rop.SAME_AS, [v_in], v_out))
+ v = v_out
+ assert isinstance(v, BoxPtr)
+ return v
+
+ def handle_write_barrier(self, op):
+ self.gen_write_barrier(self.unconstifyptr(op.getarg(0)))
+ self.newops.append(op)
+
+ def handle_malloc_operation(self, op):
+ GcRewriterAssembler.handle_malloc_operation(self, op)
+ self.known_local.add(op.result)
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
@@ -69,9 +69,11 @@
namespace[funcname + '_descr'] = getattr(self.gc_ll_descr,
'%s_descr' % funcname)
#
- ops = parse(frm_operations, namespace=namespace)
+ ops = parse(frm_operations, namespace=namespace,
+ invent_fail_descr=False)
expected = parse(to_operations % Evaluator(namespace),
- namespace=namespace)
+ namespace=namespace,
+ invent_fail_descr=False)
operations = self.gc_ll_descr.rewrite_assembler(self.cpu,
ops.operations,
[])
diff --git a/pypy/jit/backend/llsupport/test/test_stmrewrite.py b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
--- a/pypy/jit/backend/llsupport/test/test_stmrewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
@@ -1,3 +1,4 @@
+from pypy.jit.backend.llsupport.descr import *
from pypy.jit.backend.llsupport.gc import *
from pypy.jit.metainterp.gc import get_description
from pypy.jit.backend.llsupport.test.test_rewrite import RewriteTests
@@ -29,10 +30,25 @@
setfield_gc(p1, p2, descr=tzdescr)
jump()
""", """
+ [p1, p2]
+ cond_call_gc_wb(p1, 0, descr=wbdescr)
+ setfield_gc(p1, p2, descr=tzdescr)
+ jump()
+ """)
+
+ def test_rewrite_setfield_gc_on_local(self):
+ self.check_rewrite("""
[p1]
- cond_call_gc_wb(p1, 0, descr=wbdescr)
- setfield_gc(p2, p2, descr=tzdescr)
- jump()
+ p2 = new(descr=tdescr)
+ setfield_gc(p2, p1, descr=tzdescr)
+ jump(p2)
+ """, """
+ [p1]
+ p2 = call_malloc_gc(ConstClass(malloc_big_fixedsize), \
+ %(tdescr.size)d, %(tdescr.tid)d, \
+ descr=malloc_big_fixedsize_descr)
+ setfield_gc(p2, p1, descr=tzdescr)
+ jump(p2)
""")
def test_rewrite_unrelated_setfield_gcs(self):
@@ -81,6 +97,16 @@
jump(p1)
""")
+ def test_remove_debug_merge_point(self):
+ self.check_rewrite("""
+ [i1, i2]
+ debug_merge_point(i1, i2)
+ jump()
+ """, """
+ [i1, i2]
+ jump()
+ """)
+
def test_ignore_some_operations(self):
oplist = [
"guard_true(i1) [i2]", # all guards
@@ -90,7 +116,6 @@
"i3 = force_token()",
"i3 = read_timestamp()",
"i3 = mark_opaque_ptr(p1)",
- "debug_merge_point(i1, i2)",
"jit_debug(i1, i2)",
"keepalive(i1)",
"i3 = int_sub_ovf(i1, i2)", # is_ovf operations
@@ -238,6 +263,21 @@
jump(p2)
""")
+ def test_rewrite_getfield_gc_on_local_2(self):
+ self.check_rewrite("""
+ [p1]
+ p1 = new(descr=tdescr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ jump(p2)
+ """, """
+ [p1]
+ p1 = call_malloc_gc(ConstClass(malloc_fixedsize), \
+ %(tdescr.size)d, %(tdescr.tid)d, \
+ descr=malloc_fixedsize_descr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ jump(p2)
+ """)
+
def test_rewrite_getfield_gc_on_future_local(self):
self.check_rewrite("""
[p1]
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -149,12 +149,8 @@
return rop._CANRAISE_FIRST <= self.getopnum() <= rop._CANRAISE_LAST
def is_malloc(self):
- # a slightly different meaning from can_malloc
return rop._MALLOC_FIRST <= self.getopnum() <= rop._MALLOC_LAST
- def can_malloc(self):
- return self.is_call() or self.is_malloc()
-
def is_call(self):
return rop._CALL_FIRST <= self.getopnum() <= rop._CALL_LAST
diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -62,12 +62,12 @@
assert op.result == 'c'
assert op.getdescr() is mydescr
-def test_can_malloc():
+def test_is_malloc():
mydescr = AbstractDescr()
- assert rop.ResOperation(rop.rop.NEW, [], 'b').can_malloc()
+ assert rop.ResOperation(rop.rop.NEW, [], 'b').is_malloc()
call = rop.ResOperation(rop.rop.CALL, ['a', 'b'], 'c', descr=mydescr)
- assert call.can_malloc()
- assert not rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c').can_malloc()
+ assert not call.is_malloc()
+ assert not rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c').is_malloc()
def test_get_deep_immutable_oplist():
ops = [rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c')]
More information about the pypy-commit
mailing list