Example #1
0
 def rewrite(self, operations):
     # we can only remember one malloc since the next malloc can possibly
     # collect; but we can try to collapse several known-size mallocs into
     # one, both for performance and to reduce the number of write
     # barriers.  We do this on each "basic block" of operations, which in
     # this case means between CALLs or unknown-size mallocs.
     #
     operations = self.remove_bridge_exception(operations)
     for i in range(len(operations)):
         op = operations[i]
         assert op.get_forwarded() is None
         if op.getopnum() == rop.DEBUG_MERGE_POINT:
             continue
         # ---------- GETFIELD_GC ----------
         if op.getopnum() in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F,
                              rop.GETFIELD_GC_R):
             self.handle_getfield_gc(op)
             continue
         # ---------- turn NEWxxx into CALL_MALLOC_xxx ----------
         if op.is_malloc():
             self.handle_malloc_operation(op)
             continue
         if (op.is_guard() or
                 self.could_merge_with_next_guard(op, i, operations)):
             self.emit_pending_zeros()
         elif op.can_malloc():
             self.emitting_an_operation_that_can_collect()
         elif op.getopnum() == rop.LABEL:
             self.emitting_an_operation_that_can_collect()
             self._known_lengths.clear()
         # ---------- write barriers ----------
         if self.gc_ll_descr.write_barrier_descr is not None:
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
                 self.handle_write_barrier_setfield(op)
                 continue
             if op.getopnum() == rop.SETINTERIORFIELD_GC:
                 self.handle_write_barrier_setinteriorfield(op)
                 continue
             if op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
                 self.handle_write_barrier_setarrayitem(op)
                 continue
         else:
             # this is dead code, but in case we have a gc that does
             # not have a write barrier and does not zero memory, we would
             # need to clal it
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
             elif op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
         # ---------- call assembler -----------
         if OpHelpers.is_call_assembler(op.getopnum()):
             self.handle_call_assembler(op)
             continue
         if op.getopnum() == rop.JUMP or op.getopnum() == rop.FINISH:
             self.emit_pending_zeros()
         #
         self.emit_op(op)
     return self._newops
Example #2
0
 def rewrite(self, operations, gcrefs_output_list):
     # we can only remember one malloc since the next malloc can possibly
     # collect; but we can try to collapse several known-size mallocs into
     # one, both for performance and to reduce the number of write
     # barriers.  We do this on each "basic block" of operations, which in
     # this case means between CALLs or unknown-size mallocs.
     #
     self.gcrefs_output_list = gcrefs_output_list
     self.gcrefs_map = None
     self.gcrefs_recently_loaded = None
     operations = self.remove_bridge_exception(operations)
     self._changed_op = None
     for i in range(len(operations)):
         op = operations[i]
         if op.get_forwarded():
             msg = '[rewrite] operations at %d has forwarded info %s\n' % (
                 i, op.repr({}))
             if we_are_translated():
                 llop.debug_print(lltype.Void, msg)
             raise NotImplementedError(msg)
         if op.getopnum() == rop.DEBUG_MERGE_POINT:
             continue
         if op is self._changed_op:
             op = self._changed_op_to
         # ---------- GC_LOAD/STORE transformations --------------
         if self.transform_to_gc_load(op):
             continue
         # ---------- turn NEWxxx into CALL_MALLOC_xxx ----------
         if rop.is_malloc(op.opnum):
             self.handle_malloc_operation(op)
             continue
         if (rop.is_guard(op.opnum)
                 or self.could_merge_with_next_guard(op, i, operations)):
             self.emit_pending_zeros()
         elif rop.can_malloc(op.opnum):
             self.emitting_an_operation_that_can_collect()
         elif op.getopnum() == rop.LABEL:
             self.emit_label()
         # ---------- write barriers ----------
         if self.gc_ll_descr.write_barrier_descr is not None:
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
                 self.handle_write_barrier_setfield(op)
                 continue
             if op.getopnum() == rop.SETINTERIORFIELD_GC:
                 self.handle_write_barrier_setinteriorfield(op)
                 continue
             if op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
                 self.handle_write_barrier_setarrayitem(op)
                 continue
         else:
             # this is dead code, but in case we have a gc that does
             # not have a write barrier and does not zero memory, we would
             # need to call it
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
             elif op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
         # ---------- call assembler -----------
         if OpHelpers.is_call_assembler(op.getopnum()):
             self.handle_call_assembler(op)
             continue
         if op.getopnum() == rop.JUMP or op.getopnum() == rop.FINISH:
             self.emit_pending_zeros()
         #
         self.emit_op(op)
     return self._newops
Example #3
0
 def rewrite(self, operations, gcrefs_output_list):
     # we can only remember one malloc since the next malloc can possibly
     # collect; but we can try to collapse several known-size mallocs into
     # one, both for performance and to reduce the number of write
     # barriers.  We do this on each "basic block" of operations, which in
     # this case means between CALLs or unknown-size mallocs.
     #
     self.gcrefs_output_list = gcrefs_output_list
     self.gcrefs_map = None
     self.gcrefs_recently_loaded = None
     operations = self.remove_bridge_exception(operations)
     self._changed_op = None
     for i in range(len(operations)):
         op = operations[i]
         if op.get_forwarded():
             msg = '[rewrite] operations at %d has forwarded info %s\n' % (i, op.repr({}))
             if we_are_translated():
                 llop.debug_print(lltype.Void, msg)
             raise NotImplementedError(msg)
         if op.getopnum() == rop.DEBUG_MERGE_POINT:
             continue
         if op is self._changed_op:
             op = self._changed_op_to
         # ---------- GC_LOAD/STORE transformations --------------
         if self.transform_to_gc_load(op):
             continue
         # ---------- turn NEWxxx into CALL_MALLOC_xxx ----------
         if rop.is_malloc(op.opnum):
             self.handle_malloc_operation(op)
             continue
         if (rop.is_guard(op.opnum) or
                 self.could_merge_with_next_guard(op, i, operations)):
             self.emit_pending_zeros()
         elif rop.can_malloc(op.opnum):
             self.emitting_an_operation_that_can_collect()
         elif op.getopnum() == rop.LABEL:
             self.emit_label()
         # ---------- write barriers ----------
         if self.gc_ll_descr.write_barrier_descr is not None:
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
                 self.handle_write_barrier_setfield(op)
                 continue
             if op.getopnum() == rop.SETINTERIORFIELD_GC:
                 self.handle_write_barrier_setinteriorfield(op)
                 continue
             if op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
                 self.handle_write_barrier_setarrayitem(op)
                 continue
         else:
             # this is dead code, but in case we have a gc that does
             # not have a write barrier and does not zero memory, we would
             # need to clal it
             if op.getopnum() == rop.SETFIELD_GC:
                 self.consider_setfield_gc(op)
             elif op.getopnum() == rop.SETARRAYITEM_GC:
                 self.consider_setarrayitem_gc(op)
         # ---------- call assembler -----------
         if OpHelpers.is_call_assembler(op.getopnum()):
             self.handle_call_assembler(op)
             continue
         if op.getopnum() == rop.JUMP or op.getopnum() == rop.FINISH:
             self.emit_pending_zeros()
         #
         self.emit_op(op)
     return self._newops