[pypy-commit] pypy clean-exported-state: Ensure all optimization info is removed from all data referenced by ExportedState

sbauman pypy.commits at gmail.com
Wed Oct 12 11:28:27 EDT 2016


Author: Spenser Bauman <sabauma at gmail.com>
Branch: clean-exported-state
Changeset: r87721:9e5f013afa17
Date: 2016-10-12 11:27 -0400
http://bitbucket.org/pypy/pypy/changeset/9e5f013afa17/

Log:	Ensure all optimization info is removed from all data referenced by
	ExportedState

	Two cases to watch for:
	* After the ExportedState is constructed
	* When optimization fails (InvalidLoop) and the ExportedState object
	is reused for for another attempt (i.e. retracing)

diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -126,6 +126,10 @@
         return opt.optimize_peeled_loop(self.trace, self.celltoken, self.state,
             self.call_pure_results, self.inline_short_preamble)
 
+    def forget_optimization_info(self):
+        self.state.forget_optimization_info()
+        CompileData.forget_optimization_info(self)
+
 def show_procedures(metainterp_sd, procedure=None, error=None):
     # debugging
     if option and (option.view or option.viewloops):
@@ -515,7 +519,7 @@
     for item in lst:
         item.set_forwarded(None)
         # XXX we should really do it, but we need to remember the values
-        #     somehoe for ContinueRunningNormally
+        #     somehow for ContinueRunningNormally
         if reset_values:
             item.reset_value()
 
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -27,6 +27,9 @@
 class LoopInfo(object):
     label_op = None
 
+    def forget_optimization_info(self):
+        pass
+
 class BasicLoopInfo(LoopInfo):
     def __init__(self, inputargs, quasi_immutable_deps, jump_op):
         self.inputargs = inputargs
@@ -561,7 +564,8 @@
         return (BasicLoopInfo(trace.inputargs, self.quasi_immutable_deps, last_op),
                 self._newoperations)
 
-    def _clean_optimization_info(self, lst):
+    @staticmethod
+    def _clean_optimization_info(lst):
         for op in lst:
             if op.get_forwarded() is not None:
                 op.set_forwarded(None)
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -462,7 +462,6 @@
             op = produced_op.short_op.res
             if not isinstance(op, Const):
                 self._expand_info(op, infos)
-        self.optimizer._clean_optimization_info(end_args)
         return ExportedState(label_args, end_args, virtual_state, infos,
                              short_boxes, renamed_inputargs,
                              short_inputargs, runtime_boxes, memo)
@@ -472,6 +471,7 @@
         # to actually emit. Update the info
         assert (len(exported_state.next_iteration_args) ==
                 len(targetargs))
+        exported_state._check_no_forwarding(self)
         for i, target in enumerate(exported_state.next_iteration_args):
             source = targetargs[i]
             assert source is not target
@@ -542,6 +542,7 @@
         self.short_inputargs = short_inputargs
         self.runtime_boxes = runtime_boxes
         self.dump(memo)
+        self.forget_optimization_info()
 
     def dump(self, memo):
         if have_debug_prints():
@@ -551,5 +552,32 @@
                 debug_print("  " + box.repr(memo))
             debug_stop("jit-log-exported-state")
 
+    def _check_no_forwarding(self, optimizer):
+        """ Ensures that no optimization state is attached to relevant operations
+        before importing anything. """
+        shortops = [pop.short_op.res for pop in self.short_boxes]
+        optimizer._check_no_forwarding([
+            self.end_args, self.next_iteration_args, self.renamed_inputargs,
+            self.short_inputargs, shortops, self.exported_infos.keys()])
+
+    def forget_optimization_info(self):
+        """ Clean up optimization info on all operations stored in the ExportedState.
+
+        This function needs to be called when exporting the optimizer state to
+        prevent leaking of optimization information between invocations of the
+        optimizer.
+
+        That includes cleaning up in the event that optimize_peeled_loop() fails
+        with an InvalidLoop exception, as optimize_peeled_loop() mutates the
+        contents of ExportedState.
+        """
+        # These first two may be subsumed by clearing self.exported_infos
+        # but I am not 100% certain
+        Optimizer._clean_optimization_info(self.end_args)
+        Optimizer._clean_optimization_info(self.next_iteration_args)
+        Optimizer._clean_optimization_info(self.renamed_inputargs)
+        Optimizer._clean_optimization_info(self.short_inputargs)
+        Optimizer._clean_optimization_info(self.exported_infos.keys())
+
     def final(self):
         return False


More information about the pypy-commit mailing list