Commits

Hakan Ardo committed a8b5a0a

add the inputarguments to the failargs of the loop to allow bridges to inherit from the short preamble of the loop

Comments (0)

Files changed (4)

pypy/jit/metainterp/compile.py

     rd_virtuals = None
     rd_pendingfields = None
 
+    parent_short_preamble = None
+    start_indexes = None
+    rd_extrafailargs = None
+    # FIXME: Add theese to copy_all_attrbutes_into
+
     CNT_INT   = -0x20000000
     CNT_REF   = -0x40000000
     CNT_FLOAT = -0x60000000
         # jitdrivers.
         from pypy.jit.metainterp.pyjitpl import MetaInterp
         metainterp = MetaInterp(metainterp_sd, jitdriver_sd)
+        if self.parent_short_preamble:
+            print
+            print
+            print self.parent_short_preamble.operations
+            print self.start_indexes
+            #import pdb; pdb.set_trace()
+
         return metainterp.handle_guard_failure(self)
     _trace_and_compile_from_bridge._dont_inline_ = True
 

pypy/jit/metainterp/optimizeopt/optimizer.py

     __metaclass__ = extendabletype
     _attrs_ = ('box', 'known_class', 'last_guard_index', 'level', 'intbound')
     last_guard_index = -1
-    start_index = -1
+    #start_index = -1
 
     level = LEVEL_UNKNOWN
     known_class = None
         self.posponedop = None
         self.exception_might_have_happened = False
         self.newoperations = []
+        self.inputargs = []
 
         self.set_optimizations(optimizations)
 
         descr = op.getdescr()
         assert isinstance(descr, compile.ResumeGuardDescr)
         modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
-        newboxes = modifier.finish(self.values, self.pendingfields)
-        #descr.start_indexes = [self.getvalue(b).start_index for b in op.getfailargs()]
+        newboxes = modifier.finish(self.values, self.pendingfields, self.inputargs)
+        # FIXME: Do we realy want to append all inputargs?
         if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
             compile.giveup()
         descr.store_final_boxes(op, newboxes)
+        #descr.start_indexes = [self.getvalue(b).start_index for b in op.getfailargs()]
         #
         if op.getopnum() == rop.GUARD_VALUE:
             if self.getvalue(op.getarg(0)) in self.bool_boxes:

pypy/jit/metainterp/optimizeopt/unroll.py

             self.optimizer = self.optimizer.reconstruct_for_next_iteration()
 
             jump_args = jumpop.getarglist()
-            for i in range(len(jump_args)):
-                self.getvalue(jump_args[i]).start_index = i
+            #for i in range(len(jump_args)):
+            #    self.getvalue(jump_args[i]).start_index = i
+
             jumpop.initarglist([])            
             inputargs = self.inline(self.cloned_operations,
                                     loop.inputargs, jump_args)
                 for op in short_loop.operations:
                     if op.result:
                         op.result.forget_value()
+
+                for op in loop.operations:
+                    if op.is_guard():
+                        descr = op.getdescr()
+                        descr.start_indexes = []
+                        for box in op.getfailargs():
+                            try:
+                                i = loop.inputargs.index(box)
+                            except ValueError:
+                                i = -1
+                            descr.start_indexes.append(i)
+                        descr.parent_short_preamble = short_loop
+                            
+                                
                 
 
     def inline(self, loop_operations, loop_args, jump_args):
         for v in self.optimizer.values.values():
             v.last_guard_index = -1 # FIXME: Are there any more indexes stored?
 
-        inputargs = []
+        self.optimizer.inputargs = inputargs = []
         seen_inputargs = {}
         for arg in jump_args:
             boxes = []
 
         # This loop is equivalent to the main optimization loop in
         # Optimizer.propagate_all_forward
+        boxes_created_this_iteration = {}
+        last_emitted_len = -1
         for newop in loop_operations:
             if newop.getopnum() == rop.JUMP:
                 newop.initarglist(inputargs)
             newop = inliner.inline_op(newop, clone=False)
+            
+            self.optimizer.first_optimization.propagate_forward(newop)
 
-            self.optimizer.first_optimization.propagate_forward(newop)
+            # This should take care of updating inputargs in most cases i.e.
+            # when newoperations is not reorder too much. The rest should be
+            # pacthed below. Bridges will only be able to inherit the part of
+            # the short preamble that produces the boxes that are placed in 
+            # inputargs before the guard producing the bridge is emitted.
+            i = max(last_emitted_len - 2, 0)
+            while i < len(self.optimizer.newoperations):
+                op = self.optimizer.newoperations[i]
+                boxes_created_this_iteration[op.result] = True
+                for a in op.getarglist():
+                    if not isinstance(a, Const) and not a in boxes_created_this_iteration:
+                        if a not in inputargs:
+                            inputargs.append(a)
+                i += 1
+            last_emitted_len = len(self.optimizer.newoperations)
 
         # Remove jump to make sure forced code are placed before it
         newoperations = self.optimizer.newoperations
         assert jmp.getopnum() == rop.JUMP
         self.optimizer.newoperations = newoperations[:-1]
 
-        boxes_created_this_iteration = {}
         jumpargs = jmp.getarglist()
 
         # FIXME: Should also loop over operations added by forcing things in this loop

pypy/jit/metainterp/resume.py

         _, tagbits = untag(tagged)
         return tagbits == TAGVIRTUAL
 
-    def finish(self, values, pending_setfields=[]):
+    def finish(self, values, pending_setfields=[], extra_failargs=[]):
         # compute the numbering
         storage = self.storage
         # make sure that nobody attached resume data to this guard yet
             value = values[fieldbox]
             value.get_args_for_fail(self)
 
+        for box in extra_failargs:
+            self.register_box(box)
+            
         self._number_virtuals(liveboxes, values, v)
         self._add_pending_fields(pending_setfields)
+        self._add_extra_failargs(extra_failargs)
 
         storage.rd_consts = self.memo.consts
         dump_storage(storage, liveboxes)
                 rd_pendingfields.append((descr, num, fieldnum))
         self.storage.rd_pendingfields = rd_pendingfields
 
+    def _add_extra_failargs(self, extra_failargs):
+        ibox = [self._gettagged(box) for box in extra_failargs if box.type == INT]
+        rbox = [self._gettagged(box) for box in extra_failargs if box.type == REF]
+        fbox = [self._gettagged(box) for box in extra_failargs if box.type == FLOAT]
+        self.storage.rd_extrafailargs = (ibox, rbox, fbox)
+
     def _gettagged(self, box):
         if isinstance(box, Const):
             return self.memo.getconst(box)
     def _prepare(self, storage):
         self._prepare_virtuals(storage.rd_virtuals)
         self._prepare_pendingfields(storage.rd_pendingfields)
+        self._prepare_extrafailargs(storage.rd_extrafailargs)
 
     def getvirtual(self, index):
         # Returns the index'th virtual, building it lazily if needed.
                 struct = self.decode_ref(num)
                 self.setfield(descr, struct, fieldnum)
 
+    def _prepare_extrafailargs(self, extrafailargs):
+        pass
+
     def _prepare_next_section(self, info):
         # Use info.enumerate_vars(), normally dispatching to
         # pypy.jit.codewriter.jitcode.  Some tests give a different 'info'.
         self.liveboxes = [None] * metainterp.cpu.get_latest_value_count()
         self._prepare(storage)
 
+    def _prepare_extrafailargs(self, extrafailargs):
+        ibox, rbox, fbox = extrafailargs
+        for num in ibox:
+            self.decode_box(num, INT)
+        for num in rbox:
+            self.decode_box(num, REF)
+        for num in fbox:
+            self.decode_box(num, FLOAT)
+
     def consume_boxes(self, info, boxes_i, boxes_r, boxes_f):
         self.boxes_i = boxes_i
         self.boxes_r = boxes_r