def run_loop(self): cpu = self.builder.cpu self.clear_state() # disable check for now # exc = cpu.grab_exc_value() # assert not exc arguments = [] for box in self.loop.inputargs: if box.type == INT: arguments.append(getint(box)) elif box.type == FLOAT: arguments.append(getfloatstorage(box)) else: assert 0, box.type deadframe = cpu.execute_token(self.runjitcelltoken(), *arguments) fail = cpu.get_latest_descr(deadframe) do_assert(fail is self.should_fail_by.getdescr(), "Got %r, expected %r" % (fail, self.should_fail_by.getdescr())) for i, v in enumerate(self.get_fail_args()): if v not in self.expected: assert v.getopnum() == rop.SAME_AS_I # special case assert isinstance(v.getarg(0), ConstInt) self.expected[v] = getint(v.getarg(0)) if v.type == FLOAT: value = cpu.get_float_value(deadframe, i) else: value = cpu.get_int_value(deadframe, i) do_assert(value == self.expected[v], "Got %r, expected %r for value #%d" % (value, self.expected[v], i) ) exc = cpu.grab_exc_value(deadframe) if (self.guard_op is not None and rop.is_guard_exception(self.guard_op.getopnum())): if self.guard_op.getopnum() == rop.GUARD_NO_EXCEPTION: do_assert(exc, "grab_exc_value() should not be %r" % (exc,)) else: do_assert(not exc, "unexpected grab_exc_value(): %r" % (exc,))
def run_loop(self): cpu = self.builder.cpu self.clear_state() # disable check for now # exc = cpu.grab_exc_value() # assert not exc arguments = [] for box in self.loop.inputargs: if box.type == INT: arguments.append(getint(box)) elif box.type == FLOAT: arguments.append(getfloatstorage(box)) else: assert 0, box.type deadframe = cpu.execute_token(self.runjitcelltoken(), *arguments) fail = cpu.get_latest_descr(deadframe) do_assert( fail is self.should_fail_by.getdescr(), "Got %r, expected %r" % (fail, self.should_fail_by.getdescr())) for i, v in enumerate(self.get_fail_args()): if v not in self.expected: assert v.getopnum() == rop.SAME_AS_I # special case assert isinstance(v.getarg(0), ConstInt) self.expected[v] = getint(v.getarg(0)) if v.type == FLOAT: value = cpu.get_float_value(deadframe, i) else: value = cpu.get_int_value(deadframe, i) do_assert( value == self.expected[v], "Got %r, expected %r for value #%d" % (value, self.expected[v], i)) exc = cpu.grab_exc_value(deadframe) if (self.guard_op is not None and rop.is_guard_exception(self.guard_op.getopnum())): if self.guard_op.getopnum() == rop.GUARD_NO_EXCEPTION: do_assert(exc, "grab_exc_value() should not be %r" % (exc, )) else: do_assert(not exc, "unexpected grab_exc_value(): %r" % (exc, ))
def build_bridge(self): 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 if self.dont_generate_more: return False r = self.r guard_op = self.guard_op fail_args = guard_op.getfailargs() fail_descr = guard_op.getdescr() op = self.should_fail_by if not op.getfailargs(): return False for _fail_box in fail_args: _fail_box.set_forwarded(None) # generate the branch: a sequence of operations that ends in a FINISH subloop = DummyLoop([]) self.subloops.append(subloop) # keep around for debugging if rop.is_guard_exception(guard_op.getopnum()): subloop.operations.append(exc_handling(guard_op)) bridge_builder = self.builder.fork(self.builder.cpu, subloop, op.getfailargs()[:]) self.generate_ops(bridge_builder, r, subloop, op.getfailargs()[:]) # note that 'self.guard_op' now points to the guard that will fail in # this new bridge, while 'guard_op' still points to the guard that # has just failed. if r.random() < 0.1 and self.guard_op is None: # Occasionally, instead of ending in a FINISH, we end in a jump # to another loop. We don't do it, however, if the new bridge's # execution will hit 'self.guard_op', but only if it executes # to the FINISH normally. (There is no point to the extra # complexity, as we might get the same effect by two calls # to build_bridge().) # First make up the other loop... # # New restriction: must have the same argument count and types # as the original loop subset = [] for box in self.loop.inputargs: srcbox = r.choice(fail_args) if srcbox.type != box.type: if box.type == INT: srcbox = ConstInt(r.random_integer()) elif box.type == FLOAT: srcbox = ConstFloat(r.random_float_storage()) else: raise AssertionError(box.type) subset.append(srcbox) # args = [] for x in subset: if x.type == INT: args.append(InputArgInt(getint(x))) elif x.type == FLOAT: args.append(InputArgFloat(getfloatstorage(x))) else: assert 0, x.type rl = RandomLoop(self.builder.cpu, self.builder.fork, r, args) # done self.should_fail_by = rl.should_fail_by self.expected = rl.expected assert len(rl.loop.inputargs) == len(args) # The new bridge's execution will end normally at its FINISH. # Just replace the FINISH with the JUMP to the new loop. jump_op = ResOperation(rop.JUMP, subset, descr=rl.loop._targettoken) subloop.operations[-1] = jump_op self.guard_op = rl.guard_op self.prebuilt_ptr_consts += rl.prebuilt_ptr_consts self.loop._jitcelltoken.record_jump_to(rl.loop._jitcelltoken) self.dont_generate_more = True if r.random() < .05: return False dump(subloop) self.builder.cpu.compile_bridge(fail_descr, fail_args, subloop.operations, self.loop._jitcelltoken) if self.output: bridge_builder.print_loop(self.output, fail_descr, fail_args) return True