[pypy-svn] pypy out-of-line-guards: replace ropaque calls with simple flag on the looptoken. Backends have to

fijal commits-noreply at bitbucket.org
Wed Feb 9 10:28:23 CET 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: out-of-line-guards
Changeset: r41725:4a84157ae216
Date: 2011-02-07 20:47 +0200
http://bitbucket.org/pypy/pypy/changeset/4a84157ae216/

Log:	replace ropaque calls with simple flag on the looptoken. Backends
	have to be adjusted.

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
@@ -81,6 +81,7 @@
     """Try to compile a new loop by closing the current history back
     to the first operation.
     """
+    assert not metainterp.invalidated_array[0]
     history = metainterp.history
     loop = create_empty_loop(metainterp)
     loop.inputargs = history.inputargs
@@ -92,6 +93,7 @@
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
     loop_token = make_loop_token(len(loop.inputargs), jitdriver_sd)
+    loop_token.invalidated_array = metainterp.invalidated_array
     loop.token = loop_token
     loop.operations[-1].setdescr(loop_token)     # patch the target of the JUMP
     try:
@@ -102,9 +104,6 @@
     if old_loop_token is not None:
         metainterp.staticdata.log("reusing old loop")
         return old_loop_token
-    if we_are_translated() or hasattr(metainterp, 'remember_jit_invariants'):
-        # for tests
-        metainterp.remember_jit_invariants(loop)
     send_loop_to_backend(metainterp_sd, loop, "loop")
     insert_loop_token(old_loop_tokens, loop_token)
     record_loop_or_bridge(loop)
@@ -547,6 +546,7 @@
     #
     # Attempt to use optimize_bridge().  This may return None in case
     # it does not work -- i.e. none of the existing old_loop_tokens match.
+    assert not metainterp.invalidated_array[0]
     new_loop = create_empty_loop(metainterp)
     new_loop.inputargs = metainterp.history.inputargs
     # clone ops, as optimize_bridge can mutate the ops
@@ -567,9 +567,6 @@
         # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
         prepare_last_operation(new_loop, target_loop_token)
         resumekey.compile_and_attach(metainterp, new_loop)
-        if we_are_translated() or hasattr(metainterp, 'remember_jit_invariants'):
-            # for tests
-            metainterp.remember_jit_invariants(new_loop)
         record_loop_or_bridge(new_loop)
     return target_loop_token
 

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
@@ -5,7 +5,7 @@
 import sys
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.jit.metainterp import history
@@ -21,7 +21,6 @@
 class MiniStats:
     pass
 
-
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
@@ -285,6 +284,9 @@
         return self.getdescr(symbolic.get_size(S))
 
 
+# can't be on LLtypeCPU thanks to closures not rendered correctly
+INVALIDATED_ARRAY_TP = rffi.CArray(lltype.Signed)
+
 class LLtypeCPU(BaseCPU):
     is_oo = False
     ts = llhelper
@@ -488,32 +490,21 @@
         self.latest_frame = frame
         return self.get_fail_descr_from_number(fail_index)
 
+    def create_invalidate_array(self):
+        v = lltype.malloc(INVALIDATED_ARRAY_TP, 1, flavor='raw',
+                          track_allocation=False)
+        v[0] = 0
+        return v
+
     def get_invalidate_asm(self, TP, fieldname):
         def invalidate_asm(arg):
             next = getattr(arg, fieldname)
             all = []
             while next:
-                llx = llmemory.weakref_deref(ropaque.ROPAQUE, next.address)
+                llx = rffi.cast(lltype.Ptr(INVALIDATED_ARRAY_TP), next.address)
                 if llx:
-                    all.append(ropaque.cast_ropaque_to_obj(history.LoopToken,
-                                                           llx))
+                    llx[0] = 1
                 next = next.next
-
-            while all:
-                next = all.pop()
-                next.invalidated = True
-                compiled = next.compiled_loop_token.compiled_version
-                llimpl.mark_as_invalid(compiled)
-                for elem in next._back_looptokens_call_asm:
-                    token = elem()
-                    if token:
-                        tk = token.compiled_loop_token.compiled_version
-                        llimpl.invalidate_call_asm(tk,
-                                                   next.compiled_loop_token)
-                for elem in next._back_looptokens:
-                    elem = elem()
-                    if elem:
-                        all.append(elem)
         return invalidate_asm
 
 class OOtypeCPU_xxx_disabled(BaseCPU):

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
@@ -1,5 +1,5 @@
 import py, os, sys
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
@@ -512,7 +512,7 @@
 
     @arguments("box", "descr", "box")
     def _opimpl_getfield_gc_invariant_any(self, box, fielddescr, c_func):
-        self.metainterp.invariant_structs.append((box, c_func))
+        self.metainterp.mark_invariant_struct(box, c_func)
         return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box)
     opimpl_getfield_gc_i_invariant = _opimpl_getfield_gc_invariant_any
     opimpl_getfield_gc_r_invariant = _opimpl_getfield_gc_invariant_any
@@ -1402,7 +1402,7 @@
         self.portal_trace_positions = []
         self.free_frames_list = []
         self.last_exc_value_box = None
-        self.invariant_structs = []
+        self.invalidated_array = self.cpu.create_invalidate_array()
 
     def perform_call(self, jitcode, boxes, greenkey=None):
         # causes the metainterp to enter the given subfunction
@@ -1842,13 +1842,16 @@
         greenkey = original_boxes[:num_green_args]
         old_loop_tokens = self.get_compiled_merge_points(greenkey)
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
-        loop_token = compile.compile_new_loop(self, old_loop_tokens, start)
-        if loop_token is not None: # raise if it *worked* correctly
-            self.set_compiled_merge_points(greenkey, old_loop_tokens)
-            raise GenerateMergePoint(live_arg_boxes, loop_token)
+        if not self.invalidated_array[0]:
+            loop_token = compile.compile_new_loop(self, old_loop_tokens, start)
+            if loop_token is not None: # raise if it *worked* correctly
+                self.set_compiled_merge_points(greenkey, old_loop_tokens)
+                raise GenerateMergePoint(live_arg_boxes, loop_token)
         self.history.operations.pop()     # remove the JUMP
 
     def compile_bridge(self, live_arg_boxes):
+        if self.invalidated_array[0]:
+            return
         num_green_args = self.jitdriver_sd.num_green_args
         greenkey = live_arg_boxes[:num_green_args]
         old_loop_tokens = self.get_compiled_merge_points(greenkey)
@@ -1863,6 +1866,9 @@
 
     def compile_done_with_this_frame(self, exitbox):
         self.gen_store_back_in_virtualizable()
+        if self.invalidated_array[0]:
+            compile.giveup()
+            return
         # temporarily put a JUMP to a pseudo-loop
         sd = self.staticdata
         result_type = self.jitdriver_sd.result_type
@@ -1889,7 +1895,10 @@
 
     def compile_exit_frame_with_exception(self, valuebox):
         self.gen_store_back_in_virtualizable()
-        # temporarily put a JUMP to a pseudo-loop
+        if self.invalidated_array[0]:
+            compile.giveup()
+            return 
+       # temporarily put a JUMP to a pseudo-loop
         self.history.record(rop.JUMP, [valuebox], None)
         sd = self.staticdata
         loop_tokens = sd.loop_tokens_exit_frame_with_exception_ref
@@ -2237,17 +2246,12 @@
         op = op.copy_and_change(rop.CALL_ASSEMBLER, args=args, descr=token)
         self.history.operations.append(op)
 
-    def remember_jit_invariants(self, loop):
-        lllooptoken = ropaque.cast_obj_to_ropaque(loop.token)
-        lltoken_weakref = llmemory.weakref_create(lllooptoken)
-        seen = {}
-        for b_struct, c_appender in self.invariant_structs:
-            if (b_struct, c_appender) not in seen:
-                adr = heaptracker.int2adr(c_appender.getint())
-                ptr = llmemory.cast_adr_to_ptr(adr,
-                                               rclass.ASMCODE_APPENDER_PTR)
-                ptr(b_struct.getref_base(), lltoken_weakref)
-                seen[(b_struct, c_appender)] = None
+    def mark_invariant_struct(self, b_struct, c_appender):
+        addr = rffi.cast(lltype.Signed, self.invalidated_array)
+        func_addr = heaptracker.int2adr(c_appender.getint())
+        funcptr = llmemory.cast_adr_to_ptr(func_addr,
+                                           rclass.ASMCODE_APPENDER_PTR)
+        funcptr(b_struct.getref_base(), addr)
 
 # ____________________________________________________________
 

diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -606,7 +606,7 @@
                     prev.next = new_asmcode
 
             args_s = [lltype_to_annotation(llmemory.GCREF),
-                      lltype_to_annotation(llmemory.WeakRefPtr)]
+                      lltype_to_annotation(lltype.Signed)]
             s_result = lltype_to_annotation(lltype.Void)
             mixlevelann = MixLevelHelperAnnotator(self.cpu.rtyper)
             c_appender = mixlevelann.constfunc(appender, args_s, s_result)

diff --git a/pypy/jit/metainterp/memmgr.py b/pypy/jit/metainterp/memmgr.py
--- a/pypy/jit/metainterp/memmgr.py
+++ b/pypy/jit/metainterp/memmgr.py
@@ -67,6 +67,7 @@
         for looptoken in self.alive_loops.keys():
             if (looptoken.invalidated or
                 0 <= looptoken.generation < max_generation):
+                # XXX free looptoken invalidated ptr
                 del self.alive_loops[looptoken]
         newtotal = len(self.alive_loops)
         debug_print("Loop tokens freed: ", oldtotal - newtotal)

diff --git a/pypy/rpython/lltypesystem/rclass.py b/pypy/rpython/lltypesystem/rclass.py
--- a/pypy/rpython/lltypesystem/rclass.py
+++ b/pypy/rpython/lltypesystem/rclass.py
@@ -86,11 +86,13 @@
 
 # a linked-list of assembler codes to invalidate in case jit_invariant_fields
 # are modified
+# address is a pointer to a loop-level one-element raw array that's
+# either 0 or 1
 ASMCODE = lltype.GcForwardReference()
-ASMCODE.become(GcStruct('asmcode', ('address', llmemory.WeakRefPtr),
+ASMCODE.become(GcStruct('asmcode', ('address', lltype.Signed),
                         ('next', lltype.Ptr(ASMCODE))))
 
-ASMCODE_APPENDER = lltype.FuncType([llmemory.GCREF, llmemory.WeakRefPtr],
+ASMCODE_APPENDER = lltype.FuncType([llmemory.GCREF, lltype.Signed],
                                    lltype.Void)
 ASMCODE_APPENDER_PTR = lltype.Ptr(ASMCODE_APPENDER)
 


More information about the Pypy-commit mailing list