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
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] assert op.get_forwarded() is None 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