[pypy-svn] pypy out-of-line-guards: Some general progress on out-of-line guards. Merge with preambles and start

fijal commits-noreply at bitbucket.org
Thu Feb 17 16:07:30 CET 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: out-of-line-guards
Changeset: r42112:9a10c0355d10
Date: 2011-02-17 07:55 -0700
http://bitbucket.org/pypy/pypy/changeset/9a10c0355d10/

Log:	Some general progress on out-of-line guards. Merge with preambles
	and start doing the right thing when we fail such a guard

diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -49,7 +49,8 @@
         # which means mostly producing a linear list of operations and
         # inserting jumps or conditional jumps.  This is a list of tuples
         # of the shape ("opname", arg1, ..., argN) or (Label(...),).
-        ssarepr = flatten_graph(graph, regallocs, jitcode.entry_point)
+        ssarepr = flatten_graph(graph, regallocs,
+                                entry_point=jitcode.entry_point)
         #
         # step 3b: compute the liveness around certain operations
         compute_liveness(ssarepr)

diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -105,6 +105,7 @@
     loop.preamble = create_empty_loop(metainterp, 'Preamble ')
     loop.preamble.inputargs = loop.inputargs
     loop.preamble.token = make_loop_token(len(loop.inputargs), jitdriver_sd)
+    loop.preamble.token.invalidated_array = metainterp.invalidated_array
     loop.preamble.start_resumedescr = start_resumedescr
 
     try:
@@ -400,6 +401,23 @@
         self.copy_all_attrbutes_into(res)
         return res
 
+class ResumeGuardInvalidatedDescr(ResumeGuardDescr):
+    def __init__(self, metainterp_sd, jitdriver_sd):
+        self.metainterp_sd = metainterp_sd
+        self.jitdriver_sd = jitdriver_sd
+
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        # Failures of GUARD_NOT_INVALIDATED are never compiled,
+        # but always blackhole.
+        from pypy.jit.metainterp.blackhole import resume_in_blackhole
+        resume_in_blackhole(metainterp_sd, jitdriver_sd, self)
+        assert 0
+
+    def _clone_if_mutable(self):
+        res = ResumeGuardInvalidatedDescr(self.metainterp_sd, self.jitdriver_sd)
+        self.copy_all_attrbutes_into(res)
+        return res
+
 class ResumeGuardForcedDescr(ResumeGuardDescr):
 
     def __init__(self, metainterp_sd, jitdriver_sd):

diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -123,7 +123,8 @@
         clt = original_loop_token.compiled_loop_token
         clt.loop_and_bridges.append(c)
         clt.compiling_a_bridge()
-        self._compile_loop_or_bridge(c, inputargs, operations)
+        self._compile_loop_or_bridge(c, inputargs, operations,
+                                     original_loop_token.invalidated_array)
         old, oldindex = faildescr._compiled_fail
         llimpl.compile_redirect_fail(old, oldindex, c)
 
@@ -138,14 +139,16 @@
         clt.loop_and_bridges = [c]
         clt.compiled_version = c
         looptoken.compiled_loop_token = clt
-        self._compile_loop_or_bridge(c, inputargs, operations)
+        self._compile_loop_or_bridge(c, inputargs, operations,
+                                     looptoken.invalidated_array)
 
     def free_loop_and_bridges(self, compiled_loop_token):
         for c in compiled_loop_token.loop_and_bridges:
             llimpl.mark_as_free(c)
         model.AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
 
-    def _compile_loop_or_bridge(self, c, inputargs, operations):
+    def _compile_loop_or_bridge(self, c, inputargs, operations,
+                                invalidated_array):
         var2index = {}
         for box in inputargs:
             if isinstance(box, history.BoxInt):
@@ -158,6 +161,7 @@
             else:
                 raise Exception("box is: %r" % (box,))
         self._compile_operations(c, operations, var2index)
+        llimpl.compile_add_inv_array(c, invalidated_array)
         return c
 
     def _compile_operations(self, c, operations, var2index):

diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -168,7 +168,6 @@
 
 class CompiledLoop(object):
     has_been_freed = False
-    invalidated = False
 
     def __init__(self):
         self.inputargs = []
@@ -294,34 +293,15 @@
     del _variables[:]
     return _to_opaque(CompiledLoop())
 
+def compile_add_inv_array(loop, inv_array):
+    loop = _from_opaque(loop)
+    loop.invalidated_array = inv_array
+
 def mark_as_free(loop):
     loop = _from_opaque(loop)
     assert not loop.has_been_freed
     loop.has_been_freed = True
 
-def mark_as_invalid(loop):
-    _mark_as_invalid(_from_opaque(loop))
-
-def _mark_as_invalid(loop):
-    assert not loop.has_been_freed
-    for op in loop.operations:
-        if op.is_guard() and op.jump_target is not None:
-            _mark_as_invalid(op.jump_target)
-    loop.invalidated = True
-
-def invalidate_call_asm(from_loop, ctl):
-    from_loop = _from_opaque(from_loop)
-    _invalidate_call_asm(from_loop, ctl)
-
-def _invalidate_call_asm(from_loop, ctl):
-    for op in from_loop.operations:
-        if op.opnum == rop.CALL_ASSEMBLER:
-            call_target = op.descr().compiled_loop_token
-            if call_target is ctl:
-                op.descr = weakref.ref(op.descr()._tmp_token)
-        if op.is_guard() and op.jump_target is not None:
-            _invalidate_call_asm(op.jump_target, to_loop)
-
 def compile_start_int_var(loop):
     return compile_start_ref_var(loop, lltype.Signed)
 
@@ -901,7 +881,6 @@
         ctl = loop_token.compiled_loop_token
         if hasattr(ctl, 'redirected'):
             return self._do_call_assembler(ctl.redirected, *args)
-        assert not loop_token.invalidated
         assert not self._forced
         self._may_force = self.opindex
         try:
@@ -960,7 +939,7 @@
             raise GuardFailed
 
     def op_guard_not_invalidated(self, descr):
-        if self.loop.invalidated:
+        if self.loop.invalidated_array[0]:
             raise GuardFailed
 
 class OOFrame(Frame):
@@ -1693,9 +1672,8 @@
 setannotation(compile_add_fail, annmodel.SomeInteger())
 setannotation(compile_add_fail_arg, annmodel.s_None)
 setannotation(compile_redirect_fail, annmodel.s_None)
+setannotation(compile_add_inv_array, annmodel.s_None)
 setannotation(mark_as_free, annmodel.s_None)
-setannotation(mark_as_invalid, annmodel.s_None)
-setannotation(invalidate_call_asm, annmodel.s_None)
 
 setannotation(new_frame, s_Frame)
 setannotation(frame_clear, annmodel.s_None)

diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1085,6 +1085,9 @@
         if opnum == rop.GUARD_NOT_FORCED:
             resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
                                                    metainterp.jitdriver_sd)
+        elif opnum == rop.GUARD_NOT_INVALIDATED:
+            resumedescr = compile.ResumeGuardInvalidatedDescr(metainterp_sd,
+                                                      metainterp.jitdriver_sd)
         else:
             resumedescr = compile.ResumeGuardDescr()
         guard_op = metainterp.history.record(opnum, moreargs, None,
@@ -1696,6 +1699,7 @@
         self.resumekey = compile.ResumeFromInterpDescr(original_greenkey)
         self.history.inputargs = original_boxes[num_green_args:]
         self.seen_loop_header_for_jdindex = -1
+        self.record_guard_not_invalidated()
         try:
             self.interpret()
         except GenerateMergePoint, gmp:
@@ -2302,6 +2306,9 @@
         self.history.operations[-1] = newop
         return resbox
 
+    def record_guard_not_invalidated(self):
+        self.framestack[-1].generate_guard(rop.GUARD_NOT_INVALIDATED, None)
+
     def direct_assembler_call(self, targetjitdriver_sd):
         """ Generate a direct call to assembler for portal entry point,
         patching the CALL_MAY_FORCE that occurred just now.


More information about the Pypy-commit mailing list