def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) if self.opnum == rop.COND_CALL: RESULT_TYPE = lltype.Void v_cond = builder.get_bool_var(r) else: RESULT_TYPE = lltype.Signed v_cond = r.choice(builder.intvars) subset = builder.subset_of_intvars(r)[:4] for i in range(len(subset)): if r.random() < 0.35: subset[i] = ConstInt(r.random_integer()) # seen = [] def call_me(*args): if len(seen) == 0: seen.append(args) else: assert seen[0] == args if RESULT_TYPE is lltype.Signed: return len(args) - 42000 # TP = lltype.FuncType([lltype.Signed] * len(subset), RESULT_TYPE) ptr = llhelper(lltype.Ptr(TP), call_me) c_addr = ConstInt(ptr2int(ptr)) args = [v_cond, c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) v_cond = builder.get_bool_var(r) subset = builder.subset_of_intvars(r)[:4] for i in range(len(subset)): if r.random() < 0.35: subset[i] = ConstInt(r.random_integer()) # seen = [] def call_me(*args): if len(seen) == 0: seen.append(args) else: assert seen[0] == args # TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), call_me) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [v_cond, c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def create_op(self, opnum, args, res, descr, fail_args): res = ResOperation(opnum, args, descr) if fail_args is not None: res.setfailargs(fail_args) if self._postproces: self._postproces(res) return res
def transitive_imply(self, other, opt, loop): if self.op.getopnum() != other.op.getopnum(): # stronger restriction, intermixing e.g. <= and < would be possible return None if self.getleftkey() is not other.getleftkey(): return None if not self.rhs.is_identity(): # stronger restriction return None # this is a valid transitive guard that eliminates the loop guard opnum = self.transitive_cmpop(self.cmp_op.getopnum()) box_rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) other_rhs = self.emit_varops(opt, other.rhs, other.cmp_op.getarg(1)) compare = ResOperation(opnum, [box_rhs, other_rhs]) opt.emit_operation(compare) # guard descr = CompileLoopVersionDescr() descr.copy_all_attributes_from(self.op.getdescr()) descr.rd_vector_info = None # do not copy the accum list assert isinstance(descr, AbstractFailDescr) guard = ResOperation(self.op.getopnum(), [compare], descr=descr) guard.setfailargs(loop.label.getarglist_copy()) opt.emit_operation(guard) return guard
def create_op(self, opnum, args, res, descr, fail_args): res = ResOperation(opnum, args, descr) if fail_args is not None: res.setfailargs(fail_args) if self._postproces: self._postproces(res) return res
def transitive_imply(self, other, opt, loop): if self.op.getopnum() != other.op.getopnum(): # stronger restriction, intermixing e.g. <= and < would be possible return None if self.getleftkey() is not other.getleftkey(): return None if not self.rhs.is_identity(): # stronger restriction return None # this is a valid transitive guard that eliminates the loop guard opnum = self.transitive_cmpop(self.cmp_op.getopnum()) box_rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) other_rhs = self.emit_varops(opt, other.rhs, other.cmp_op.getarg(1)) compare = ResOperation(opnum, [box_rhs, other_rhs]) opt.emit_operation(compare) # guard descr = CompileLoopVersionDescr() descr.copy_all_attributes_from(self.op.getdescr()) descr.rd_vector_info = None # do not copy the accum list assert isinstance(descr, AbstractFailDescr) guard = ResOperation(self.op.getopnum(), [compare], descr=descr) guard.setfailargs(loop.label.getarglist_copy()) opt.emit_operation(guard) return guard
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) v_cond = builder.get_bool_var(r) subset = builder.subset_of_intvars(r)[:4] for i in range(len(subset)): if r.random() < 0.35: subset[i] = ConstInt(r.random_integer()) # seen = [] def call_me(*args): if len(seen) == 0: seen.append(args) else: assert seen[0] == args # TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), call_me) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [v_cond, c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def store_final_boxes_in_guard(self, op, pendingfields): assert pendingfields is not None descr = op.getdescr() assert isinstance(descr, compile.ResumeGuardDescr) modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) try: newboxes = modifier.finish(self, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: raise resume.TagOverflow except resume.TagOverflow: raise compile.giveup() descr.store_final_boxes(op, newboxes) # if op.getopnum() == rop.GUARD_VALUE: if self.getvalue(op.getarg(0)) in self.bool_boxes: # Hack: turn guard_value(bool) into guard_true/guard_false. # This is done after the operation is emitted to let # store_final_boxes_in_guard set the guard_opnum field of the # descr to the original rop.GUARD_VALUE. constvalue = op.getarg(1).getint() if constvalue == 0: opnum = rop.GUARD_FALSE elif constvalue == 1: opnum = rop.GUARD_TRUE else: raise AssertionError("uh?") newop = ResOperation(opnum, [op.getarg(0)], op.result, descr) newop.setfailargs(op.getfailargs()) return newop else: # a real GUARD_VALUE. Make it use one counter per value. descr.make_a_counter_per_value(op) return op
def exc_handling(guard_op): # operations need to start with correct GUARD_EXCEPTION if guard_op._exc_box is None: op = ResOperation(rop.GUARD_NO_EXCEPTION, []) else: op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box]) op.setdescr(self.builder.getfaildescr()) op.setfailargs([]) return op
def exc_handling(guard_op): # operations need to start with correct GUARD_EXCEPTION if guard_op._exc_box is None: op = ResOperation(rop.GUARD_NO_EXCEPTION, []) else: op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box]) op.setdescr(self.builder.getfaildescr()) op.setfailargs([]) return op
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(), descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def emit_operations(self, opt): # create trace instructions for the index lhs = self.emit_varops(opt, self.lhs, self.cmp_op.getarg(0)) rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) opnum = self.cmp_op.getopnum() cmp_op = ResOperation(opnum, [lhs, rhs]) opt.emit_operation(cmp_op) # emit that actual guard guard = ResOperation(self.op.getopnum(), [cmp_op], self.op.getdescr()) guard.setfailargs(self.op.getfailargs()[:]) opt.emit_operation(guard) self.setindex(opt.operation_position()-1) self.setoperation(guard) self.setcmp(cmp_op)
def emit_operations(self, opt): # create trace instructions for the index lhs = self.emit_varops(opt, self.lhs, self.cmp_op.getarg(0)) rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) opnum = self.cmp_op.getopnum() cmp_op = ResOperation(opnum, [lhs, rhs]) opt.emit_operation(cmp_op) # emit that actual guard guard = ResOperation(self.op.getopnum(), [cmp_op], self.op.getdescr()) guard.setfailargs(self.op.getfailargs()[:]) opt.emit_operation(guard) self.setindex(opt.operation_position() - 1) self.setoperation(guard) self.setcmp(cmp_op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) subset, f = self.non_raising_func_code(builder, r) RES = self.getresulttype() TP = lltype.FuncType([lltype.Signed] * len(subset), RES) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) subset, f = self.non_raising_func_code(builder, r) RES = self.getresulttype() TP = lltype.FuncType([lltype.Signed] * len(subset), RES) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstInt(ptr2int(ptr)) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstInt(ptr2int(ptr)) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=builder.getfaildescr()) op._exc_box = ConstInt(ptr2int(exc)) op.setfailargs(builder.subset_of_intvars(r)) builder.should_fail_by = op builder.guard_op = op builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) subset, f = self.non_raising_func_code(builder, r) if len(subset) == 0: RES = lltype.Void else: RES = lltype.Signed TP = lltype.FuncType([lltype.Signed] * len(subset), RES) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] builder.fakemetainterp.ovf_flag = False super(AbstractOvfOperation, self).produce_into(builder, r) if builder.fakemetainterp.ovf_flag: # overflow detected op = ResOperation(rop.GUARD_OVERFLOW, []) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including # the result, and then remove it from builder.intvars. fail_subset = builder.subset_of_intvars(r) builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_OVERFLOW, []) op.setdescr(builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] builder.fakemetainterp.ovf_flag = False super(AbstractOvfOperation, self).produce_into(builder, r) if builder.fakemetainterp.ovf_flag: # overflow detected op = ResOperation(rop.GUARD_OVERFLOW, []) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including # the result, and then remove it from builder.intvars. fail_subset = builder.subset_of_intvars(r) builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_OVERFLOW, []) op.setdescr(builder.getfaildescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def produce_into(self, builder, r): subset, f = self.non_raising_func_code(builder, r) RES = self.getresulttype() TP = lltype.FuncType([lltype.Signed] * len(subset), RES) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) _, vtableptr = builder.get_random_structure_type_and_vtable(r) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], descr=builder.getfaildescr()) op.setfailargs(builder.subset_of_intvars(r)) op._exc_box = None builder.should_fail_by = op builder.guard_op = op builder.loop.operations.append(op)
def create_op(self, opnum, args, result, descr, fail_args): if opnum == ESCAPE_OP.OPNUM: op = ESCAPE_OP(result) op.initarglist(args) assert descr is None return op if opnum == FORCE_SPILL.OPNUM: op = FORCE_SPILL(result) op.initarglist(args) assert descr is None return op else: res = ResOperation(opnum, args, result, descr) if fail_args is not None: res.setfailargs(fail_args) if self._postproces: self._postproces(res) return res
def produce_into(self, builder, r): subset, f = self.non_raising_func_code(builder, r) RES = self.getresulttype() TP = lltype.FuncType([lltype.Signed] * len(subset), RES) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) _, vtableptr = builder.get_random_structure_type_and_vtable(r) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], descr=builder.getfaildescr()) op.setfailargs(builder.subset_of_intvars(r)) op._exc_box = None builder.should_fail_by = op builder.guard_op = op builder.loop.operations.append(op)
def create_op(self, opnum, args, result, descr, fail_args): if opnum == ESCAPE_OP.OPNUM: op = ESCAPE_OP(result) op.initarglist(args) assert descr is None return op if opnum == FORCE_SPILL.OPNUM: op = FORCE_SPILL(result) op.initarglist(args) assert descr is None return op else: res = ResOperation(opnum, args, result, descr) if fail_args is not None: res.setfailargs(fail_args) if self._postproces: self._postproces(res) return res
def produce_into(self, builder, r): subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: break other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [other_box], descr=builder.getfaildescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) op.setfailargs(builder.subset_of_intvars(r)) builder.should_fail_by = op builder.guard_op = op builder.loop.operations.append(op)
def produce_into(self, builder, r): subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = self.getcalldescr(builder, TP) self.put(builder, args, descr) while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: break other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [other_box], BoxPtr(), descr=builder.getfaildescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) op.setfailargs(builder.subset_of_intvars(r)) builder.should_fail_by = op builder.guard_op = op builder.loop.operations.append(op)
def store_final_boxes_in_guard(self, op, pendingfields): assert pendingfields is not None if op.getdescr() is not None: descr = op.getdescr() assert isinstance(descr, compile.ResumeAtPositionDescr) else: descr = compile.invent_fail_descr_for_op(op.getopnum(), self) op.setdescr(descr) assert isinstance(descr, compile.ResumeGuardDescr) assert isinstance(op, GuardResOp) modifier = resume.ResumeDataVirtualAdder(descr, op, self.resumedata_memo) try: newboxes = modifier.finish(self, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: raise resume.TagOverflow except resume.TagOverflow: raise compile.giveup() descr.store_final_boxes(op, newboxes, self.metainterp_sd) # if op.getopnum() == rop.GUARD_VALUE: if self.getvalue(op.getarg(0)) in self.bool_boxes: # Hack: turn guard_value(bool) into guard_true/guard_false. # This is done after the operation is emitted to let # store_final_boxes_in_guard set the guard_opnum field of the # descr to the original rop.GUARD_VALUE. constvalue = op.getarg(1).getint() if constvalue == 0: opnum = rop.GUARD_FALSE elif constvalue == 1: opnum = rop.GUARD_TRUE else: raise AssertionError("uh?") newop = ResOperation(opnum, [op.getarg(0)], op.result, descr) newop.setfailargs(op.getfailargs()) return newop else: # a real GUARD_VALUE. Make it use one counter per value. descr.make_a_counter_per_value(op) return op