def prepare_op_call_malloc_nursery_varsize(self, op, fcond): gc_ll_descr = self.cpu.gc_ll_descr if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): raise Exception("unreachable code") # for boehm, this function should never be called arraydescr = op.getdescr() length_box = op.getarg(2) assert not isinstance(length_box, Const) # we cannot have a const here! # can only use spill_or_move_registers_before_call() as a hint if # we are sure that length_box stays alive and won't be freed now # (it should always be the case, see below, but better safe than sorry) if self.rm.stays_alive(length_box): self.rm.spill_or_move_registers_before_call([r.r0, r.r1]) # the result will be in r0 self.rm.force_allocate_reg(op, selected_reg=r.r0) # we need r1 as a temporary tmp_box = TempVar() self.rm.force_allocate_reg(tmp_box, selected_reg=r.r1) gcmap = self.get_gcmap([r.r0, r.r1]) # allocate the gcmap *before* self.rm.possibly_free_var(tmp_box) # length_box always survives: it's typically also present in the # next operation that will copy it inside the new array. It's # fine to load it from the stack too, as long as it's != r0, r1. lengthloc = self.rm.loc(length_box) self.rm.possibly_free_var(length_box) # itemsize = op.getarg(1).getint() maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize self.assembler.malloc_cond_varsize( op.getarg(0).getint(), gc_ll_descr.get_nursery_free_addr(), gc_ll_descr.get_nursery_top_addr(), lengthloc, itemsize, maxlength, gcmap, arraydescr)
def ensure_even_odd_pair(self, origvar, bindvar, bind_first=True, must_exist=True, load_loc_odd=True, move_regs=True): """ Allocates two registers that can be used by the instruction. origvar: is the original register holding the value bindvar: is the variable that will be bound (= self.reg_bindings[bindvar] = new register) bind_first: the even register will be bound to bindvar, if bind_first == False: the odd register will be bound """ self._check_type(origvar) prev_loc = self.loc(origvar, must_exist=must_exist) var2 = TempVar() if bindvar is None: bindvar = TempVar() if bind_first: loc, loc2 = self.force_allocate_reg_pair(bindvar, var2, self.temp_boxes) else: loc, loc2 = self.force_allocate_reg_pair(var2, bindvar, self.temp_boxes) if isinstance(bindvar, TempVar): self.temp_boxes.append(bindvar) self.temp_boxes.append(var2) assert loc.is_even() and loc2.is_odd() if move_regs and prev_loc is not loc2: if load_loc_odd: self.assembler.regalloc_mov(prev_loc, loc2) else: self.assembler.regalloc_mov(prev_loc, loc) return loc, loc2
def get_scratch_reg(self): box = TempVar() reg = self.force_allocate_reg(box, forbidden_vars=self.temp_boxes) self.temp_boxes.append(box) return reg