def produce_into(self, builder, r): if r.random() < 0.4: UnaryOperation.produce_into(self, builder, r) elif r.random() < 0.75 or not builder.cpu.supports_floats: self.put(builder, [ConstInt(r.random_integer())]) else: self.put(builder, [ConstFloat(r.random_float())])
def test_ResumeDataLoopMemo_other(): memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) const = ConstFloat(-1.0) tagged = memo.getconst(const) index, tagbits = untag(tagged) assert tagbits == TAGCONST assert memo.consts[index] is const
def test_make_jitdriver_callbacks_2(): def can_inline(x, y): assert x == 5 assert y == 42.5 return False CAN_INLINE = lltype.Ptr( lltype.FuncType([lltype.Signed, lltype.Float], lltype.Bool)) class FakeCell: dont_trace_here = False class FakeWarmRunnerDesc: rtyper = None green_args_spec = [lltype.Signed, lltype.Float] can_inline_ptr = llhelper(CAN_INLINE, can_inline) get_printable_location_ptr = None confirm_enter_jit_ptr = None state = WarmEnterState(FakeWarmRunnerDesc()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter state.make_jitdriver_callbacks() res = state.can_inline_callable([ConstInt(5), ConstFloat(42.5)]) assert res is False
def getvar(self, arg): if not arg: return ConstInt(0) try: return ConstInt(int(arg)) except ValueError: if self.is_float(arg): return ConstFloat(float(arg)) if arg.startswith('"') or arg.startswith("'"): # XXX ootype info = arg.strip("'\"") return ConstPtr( lltype.cast_opaque_ptr(llmemory.GCREF, llstr(info))) if arg.startswith('ConstClass('): name = arg[len('ConstClass('):-1] return self.get_const(name, 'class') elif arg == 'None': return None elif arg == 'NULL': if self.type_system == 'lltype': return ConstPtr(ConstPtr.value) else: return ConstObj(ConstObj.value) elif arg.startswith('ConstPtr('): name = arg[len('ConstPtr('):-1] return self.get_const(name, 'ptr') return self.vars[arg]
def test_ResumeDataLoopMemo_other(): memo = ResumeDataLoopMemo(LLtypeMixin.cpu) const = ConstFloat(-1.0) tagged = memo.getconst(const) index, tagbits = untag(tagged) assert tagbits == TAGCONST assert memo.consts[index] is const
def callback(asm): c = ConstFloat(longlong.getfloatstorage(-42.5)) loc = self.xrm.convert_to_imm(c) asm.mov(loc, xmm5) asm.regalloc_push(xmm5) asm.regalloc_pop(xmm0) asm.mc.CVTTSD2SI(eax, xmm0)
def produce_into(self, builder, r): if not builder.floatvars: raise CannotProduceOperation k = r.random() if k < 0.18: v_first = ConstFloat(r.random_float()) else: v_first = r.choice(builder.floatvars) if k > 0.82: v_second = ConstFloat(r.random_float()) else: v_second = r.choice(builder.floatvars) if abs(v_first.value) > 1E100 or abs(v_second.value) > 1E100: raise CannotProduceOperation # avoid infinities if abs(v_second.value) < 1E-100: raise CannotProduceOperation # e.g. division by zero error self.put(builder, [v_first, v_second])
def produce_into(self, builder, r): if not builder.floatvars: raise CannotProduceOperation k = r.random() if k < 0.18: v_first = ConstFloat(r.random_float_storage()) else: v_first = r.choice(builder.floatvars) if k > 0.82: v_second = ConstFloat(r.random_float_storage()) else: v_second = r.choice(builder.floatvars) if abs(v_first.getfloat()) > 1e100 or abs(v_second.getfloat()) > 1e100: raise CannotProduceOperation # avoid infinities if abs(v_second.getfloat()) < 1e-100: raise CannotProduceOperation # e.g. division by zero error self.put(builder, [v_first, v_second])
def test_make_unwrap_greenkey(): class FakeWarmRunnerDesc: green_args_spec = [lltype.Signed, lltype.Float] state = WarmEnterState(FakeWarmRunnerDesc()) unwrap_greenkey = state.make_unwrap_greenkey() greenargs = unwrap_greenkey([ConstInt(42), ConstFloat(42.5)]) assert greenargs == (42, 42.5) assert type(greenargs[0]) is int
def callback(asm): c = ConstFloat(longlong.getfloatstorage(-42.5)) loc = self.xrm.convert_to_imm(c) loc2 = self.fm.frame_pos(4, FLOAT) asm.mc.SUB_ri(esp.value, 64) asm.mov(loc, xmm5) asm.regalloc_push(xmm5) asm.regalloc_pop(loc2) asm.mov(loc2, xmm0) asm.mc.ADD_ri(esp.value, 64) asm.mc.CVTTSD2SI(eax, xmm0)
def test_wrap(): def _is(box1, box2): return (box1.__class__ == box2.__class__ and box1.value == box2.value) p = lltype.malloc(lltype.GcStruct('S')) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert _is(wrap(None, 42), BoxInt(42)) assert _is(wrap(None, 42.5), BoxFloat(42.5)) assert _is(wrap(None, p), BoxPtr(po)) assert _is(wrap(None, 42, in_const_box=True), ConstInt(42)) assert _is(wrap(None, 42.5, in_const_box=True), ConstFloat(42.5)) assert _is(wrap(None, p, in_const_box=True), ConstPtr(po))
def test_make_jitdriver_callbacks_1(): class FakeWarmRunnerDesc: can_inline_ptr = None get_printable_location_ptr = None confirm_enter_jit_ptr = None green_args_spec = [lltype.Signed, lltype.Float] class FakeCell: dont_trace_here = False state = WarmEnterState(FakeWarmRunnerDesc()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter state.make_jitdriver_callbacks() res = state.can_inline_callable([ConstInt(5), ConstFloat(42.5)]) assert res is True res = state.get_location_str([ConstInt(5), ConstFloat(42.5)]) assert res == '(no jitdriver.get_printable_location!)'
def test_attach_unoptimized_bridge_from_interp(): class FakeWarmRunnerDesc: green_args_spec = [lltype.Signed, lltype.Float] get_jitcell_at_ptr = None state = WarmEnterState(FakeWarmRunnerDesc()) get_jitcell = state.make_jitcell_getter() state.attach_unoptimized_bridge_from_interp( [ConstInt(5), ConstFloat(2.25)], "entry loop token") cell1 = get_jitcell(5, 2.25) assert cell1.counter < 0 assert cell1.entry_loop_token == "entry loop token"
def test_make_jitdriver_callbacks_3(): def get_location(x, y): assert x == 5 assert y == 42.5 return "hi there" # abuse the return type, but nobody checks it GET_LOCATION = lltype.Ptr( lltype.FuncType([lltype.Signed, lltype.Float], lltype.Ptr(rstr.STR))) class FakeWarmRunnerDesc: rtyper = None green_args_spec = [lltype.Signed, lltype.Float] can_inline_ptr = None get_printable_location_ptr = llhelper(GET_LOCATION, get_location) confirm_enter_jit_ptr = None get_jitcell_at_ptr = None state = WarmEnterState(FakeWarmRunnerDesc()) state.make_jitdriver_callbacks() res = state.get_location_str([ConstInt(5), ConstFloat(42.5)]) assert res == "hi there"
def test_wrap(): def _is(box1, box2): return (box1.__class__ == box2.__class__ and box1.value == box2.value) p = lltype.malloc(lltype.GcStruct('S')) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert _is(wrap(None, 42), BoxInt(42)) assert _is(wrap(None, 42.5), boxfloat(42.5)) assert _is(wrap(None, p), BoxPtr(po)) assert _is(wrap(None, 42, in_const_box=True), ConstInt(42)) assert _is(wrap(None, 42.5, in_const_box=True), constfloat(42.5)) assert _is(wrap(None, p, in_const_box=True), ConstPtr(po)) if longlong.supports_longlong: import sys from pypy.rlib.rarithmetic import r_longlong, r_ulonglong value = r_longlong(-sys.maxint * 17) assert _is(wrap(None, value), BoxFloat(value)) assert _is(wrap(None, value, in_const_box=True), ConstFloat(value)) value_unsigned = r_ulonglong(-sys.maxint * 17) assert _is(wrap(None, value_unsigned), BoxFloat(value)) sfval = r_singlefloat(42.5) ival = longlong.singlefloat2int(sfval) assert _is(wrap(None, sfval), BoxInt(ival)) assert _is(wrap(None, sfval, in_const_box=True), ConstInt(ival))
# Even if it is a VirtualValue, the 'box' can be non-None, # meaning it has been forced. return self.box is None class ConstantValue(OptValue): level = LEVEL_CONSTANT def __init__(self, box): self.box = box CONST_0 = ConstInt(0) CONST_1 = ConstInt(1) CVAL_ZERO = ConstantValue(CONST_0) CVAL_ZERO_FLOAT = ConstantValue(ConstFloat(0.0)) llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL) oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL) class AbstractVirtualValue(OptValue): _attrs_ = ('optimizer', 'keybox', 'source_op', '_cached_vinfo') box = None level = LEVEL_NONNULL _cached_vinfo = None def __init__(self, optimizer, keybox, source_op=None): self.optimizer = optimizer self.keybox = keybox # only used as a key in dictionaries self.source_op = source_op # the NEW_WITH_VTABLE/NEW_ARRAY operation # that builds this box
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, [], None) else: op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box], BoxPtr()) op.setdescr(BasicFailDescr()) 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 # generate the branch: a sequence of operations that ends in a FINISH subloop = DummyLoop([]) if guard_op.is_guard_exception(): 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 = [x.clonebox() for x in subset] rl = RandomLoop(self.builder.cpu, self.builder.fork, r, args) dump(rl.loop) self.cpu.compile_loop(rl.loop.inputargs, rl.loop.operations, rl.loop._jitcelltoken) # 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, None, 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) return True
def constfloat(x): return ConstFloat(longlong.getfloatstorage(x))
def do_cast_int_to_float(cpu, box1): return ConstFloat(float(box1.getint()))
def do_float_truediv(cpu, box1, box2): return ConstFloat(box1.getfloat() / box2.getfloat())
def do_float_mul(cpu, box1, box2): return ConstFloat(box1.getfloat() * box2.getfloat())
def do_float_sub(cpu, box1, box2): return ConstFloat(box1.getfloat() - box2.getfloat())
def do_float_add(cpu, box1, box2): return ConstFloat(box1.getfloat() + box2.getfloat())
def do_float_abs(cpu, box1): return ConstFloat(abs(box1.getfloat()))
def do_float_neg(cpu, box1): return ConstFloat(-box1.getfloat())