Author: Armin Rigo <ar...@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')] _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit