importpyfrompypy.jit.metainterp.warmspotimportget_statsfrompypy.rlib.jitimportJitDriver,set_param,unroll_safefrompypy.jit.backend.llgraphimportrunnerfrompypy.jit.metainterp.test.supportimportLLJitMixin,OOJitMixinfrompypy.jit.metainterp.optimizeoptimportALL_OPTS_NAMESclassExit(Exception):def__init__(self,result):self.result=resultclassWarmspotTests(object):deftest_basic(self):mydriver=JitDriver(reds=['a'],greens=['i'])CODE_INCREASE=0CODE_JUMP=1lst=[CODE_INCREASE,CODE_INCREASE,CODE_JUMP]definterpreter_loop(a):i=0whileTrue:mydriver.jit_merge_point(i=i,a=a)ifi>=len(lst):breakelem=lst[i]ifelem==CODE_INCREASE:a=a+1i+=1elifelem==CODE_JUMP:ifa<20:i=0mydriver.can_enter_jit(i=i,a=a)else:i+=1else:passraiseExit(a)defmain(a):try:interpreter_loop(a)exceptExit,e:returne.resultres=self.meta_interp(main,[1])assertres==21deftest_reentry(self):mydriver=JitDriver(reds=['n'],greens=[])deff(n):whilen>0:mydriver.can_enter_jit(n=n)mydriver.jit_merge_point(n=n)ifn%20==0:n-=2n-=1res=self.meta_interp(f,[60])assertres==f(30)deftest_location(self):defget_printable_location(n):return'GREEN IS %d.'%nmyjitdriver=JitDriver(greens=['n'],reds=['m'],get_printable_location=get_printable_location)deff(n,m):whilem>0:myjitdriver.can_enter_jit(n=n,m=m)myjitdriver.jit_merge_point(n=n,m=m)m-=1self.meta_interp(f,[123,10])assertlen(get_stats().locations)>=4forlocinget_stats().locations:assertloc==(0,0,123)deftest_set_param_enable_opts(self):frompypy.rpython.annlowlevelimportllstr,hlstrmyjitdriver=JitDriver(greens=[],reds=['n'])classA(object):defm(self,n):returnn-1defg(n):whilen>0:myjitdriver.can_enter_jit(n=n)myjitdriver.jit_merge_point(n=n)n=A().m(n)returnndeff(n,enable_opts):set_param(None,'enable_opts',hlstr(enable_opts))returng(n)# check that the set_param will override the defaultres=self.meta_interp(f,[10,llstr('')])assertres==0self.check_resops(new_with_vtable=1)res=self.meta_interp(f,[10,llstr(ALL_OPTS_NAMES)],enable_opts='')assertres==0self.check_resops(new_with_vtable=0)deftest_unwanted_loops(self):mydriver=JitDriver(reds=['n','total','m'],greens=[])defloop1(n):# the jit should not look here, as there is a loopres=0foriinrange(n):res+=ireturnres@unroll_safedefloop2(n):# the jit looks here, due to the decoratorforiinrange(5):n+=1returnndeff(m):total=0n=0whilen<m:mydriver.can_enter_jit(n=n,total=total,m=m)mydriver.jit_merge_point(n=n,total=total,m=m)total+=loop1(n)n=loop2(n)returntotalself.meta_interp(f,[50])self.check_enter_count_at_most(2)deftest_wanted_unrolling_and_preinlining(self):mydriver=JitDriver(reds=['n','m'],greens=[])@unroll_safedefloop2(n):# the jit looks here, due to the decoratorforiinrange(5):n+=1returnnloop2._always_inline_=Truedefg(n):returnloop2(n)g._dont_inline_=Truedeff(m):n=0whilen<m:mydriver.can_enter_jit(n=n,m=m)mydriver.jit_merge_point(n=n,m=m)n=g(n)returnnself.meta_interp(f,[50],backendopt=True)self.check_enter_count_at_most(2)self.check_resops(call=0)deftest_loop_header(self):# artificial test: we enter into the JIT only when can_enter_jit()# is seen, but we close a loop in the JIT much more quickly# because of loop_header().mydriver=JitDriver(reds=['n','m'],greens=[])deff(m):n=0whileTrue:mydriver.jit_merge_point(n=n,m=m)ifn>m:m-=1ifm<0:returnnn=0mydriver.can_enter_jit(n=n,m=m)else:n+=1mydriver.loop_header()assertf(15)==1res=self.meta_interp(f,[15],backendopt=True)assertres==1self.check_resops(int_add=2)# I get 13 without the loop_header()deftest_omit_can_enter_jit(self):# Simple test comparing the effects of always giving a can_enter_jit(),# or not giving any. Mostly equivalent, except that if given, it is# ignored the first time, and so it ends up taking one extra loop to# start JITting.mydriver=JitDriver(greens=[],reds=['m'])#fori2inrange(10):deff2(m):whilem>0:mydriver.jit_merge_point(m=m)m-=1self.meta_interp(f2,[i2])try:self.check_jitcell_token_count(1)breakexceptAssertionError:print"f2: no loop generated for i2==%d"%i2else:raise# re-raise the AssertionError: check_loop_count never 1#fori1inrange(10):deff1(m):whilem>0:mydriver.can_enter_jit(m=m)mydriver.jit_merge_point(m=m)m-=1self.meta_interp(f1,[i1])try:self.check_jitcell_token_count(1)breakexceptAssertionError:print"f1: no loop generated for i1==%d"%i1else:raise# re-raise the AssertionError: check_loop_count never 1#asserti1-1==i2deftest_no_loop_at_all(self):mydriver=JitDriver(greens=[],reds=['m'])deff2(m):mydriver.jit_merge_point(m=m)returnm-1deff1(m):whilem>0:m=f2(m)self.meta_interp(f1,[8])# it should generate one "loop" only, which ends in a FINISH# corresponding to the return from f2.self.check_trace_count(1)self.check_resops(jump=0)deftest_simple_loop(self):mydriver=JitDriver(greens=[],reds=['m'])deff1(m):whilem>0:mydriver.jit_merge_point(m=m)m=m-1self.meta_interp(f1,[8])self.check_trace_count(1)self.check_resops({'jump':1,'guard_true':2,'int_gt':2,'int_sub':2})deftest_void_red_variable(self):mydriver=JitDriver(greens=[],reds=['m'])deff1(m):a=Nonewhilem>0:mydriver.jit_merge_point(m=m)m=m-1ifm==10:pass# other caseself.meta_interp(f1,[18])deftest_bug_constant_int(self):py.test.skip("crashes because a is a constant")frompypy.rpython.lltypesystemimportlltype,rffimydriver=JitDriver(greens=['a'],reds=['m'])deff1(m,a):whilem>0:mydriver.jit_merge_point(a=a,m=m)m=m-1defentry(m):f1(m,42)self.meta_interp(entry,[18])deftest_bug_constant_instance(self):py.test.skip("crashes because a is a constant")frompypy.rpython.lltypesystemimportlltype,rffimydriver=JitDriver(greens=['a'],reds=['m'])classA(object):passa1=A()deff1(m,a):whilem>0:mydriver.jit_merge_point(a=a,m=m)m=m-1defentry(m):f1(m,a1)self.meta_interp(entry,[18])deftest_bug_constant_rawptrs(self):py.test.skip("crashes because a is a constant")frompypy.rpython.lltypesystemimportlltype,rffimydriver=JitDriver(greens=['a'],reds=['m'])deff1(m):a=lltype.nullptr(rffi.VOIDP.TO)whilem>0:mydriver.jit_merge_point(a=a,m=m)m=m-1self.meta_interp(f1,[18])deftest_bug_rawptrs(self):frompypy.rpython.lltypesystemimportlltype,rffimydriver=JitDriver(greens=['a'],reds=['m'])deff1(m):a=lltype.malloc(rffi.VOIDP.TO,5,flavor='raw')whilem>0:mydriver.jit_merge_point(a=a,m=m)m=m-1ifm==10:passlltype.free(a,flavor='raw')self.meta_interp(f1,[18])deftest_loop_automatic_reds(self):myjitdriver=JitDriver(greens=['m'],reds='auto')deff(n,m):res=0# try to have lots of red vars, so that if there is an error in# the ordering of reds, there are low chances that the test passes# by chancea=b=c=d=nwhilen>0:myjitdriver.jit_merge_point(m=m)n-=1a+=1# dummy unused redb+=2# dummy unused redc+=3# dummy unused redd+=4# dummy unused redres+=m*2returnresexpected=f(21,5)res=self.meta_interp(f,[21,5])assertres==expectedself.check_resops(int_sub=2,int_mul=0,int_add=10)deftest_loop_automatic_reds_with_floats_and_refs(self):myjitdriver=JitDriver(greens=['m'],reds='auto')classMyObj(object):def__init__(self,val):self.val=valdeff(n,m):res=0# try to have lots of red vars, so that if there is an error in# the ordering of reds, there are low chances that the test passes# by chancei1=i2=i3=i4=nf1=f2=f3=f4=float(n)r1=r2=r3=r4=MyObj(n)whilen>0:myjitdriver.jit_merge_point(m=m)n-=1i1+=1# dummy unused redi2+=2# dummy unused redi3+=3# dummy unused redi4+=4# dummy unused redf1+=1# dummy unused redf2+=2# dummy unused redf3+=3# dummy unused redf4+=4# dummy unused redr1.val+=1# dummy unused redr2.val+=2# dummy unused redr3.val+=3# dummy unused redr4.val+=4# dummy unused redres+=m*2returnresexpected=f(21,5)res=self.meta_interp(f,[21,5])assertres==expectedself.check_resops(int_sub=2,int_mul=0,int_add=18,float_add=8)deftest_loop_automatic_reds_livevars_before_jit_merge_point(self):myjitdriver=JitDriver(greens=['m'],reds='auto')deff(n,m):res=0whilen>0:n-=1myjitdriver.jit_merge_point(m=m)res+=m*2returnresexpected=f(21,5)res=self.meta_interp(f,[21,5])assertres==expectedself.check_resops(int_sub=2,int_mul=0,int_add=2)deftest_inline_jit_merge_point(self):# test that the machinery to inline jit_merge_points in callers# works. The final user does not need to mess manually with the# _inline_jit_merge_point_ attribute and similar, it is all nicely# handled by @JitDriver.inline()myjitdriver=JitDriver(greens=['a'],reds='auto')defjit_merge_point(a,b):myjitdriver.jit_merge_point(a=a)defadd(a,b):jit_merge_point(a,b)returna+badd._inline_jit_merge_point_=jit_merge_pointmyjitdriver.inline_jit_merge_point=Truedefcalc(n):res=0whileres<1000:res=add(n,res)returnresdeff():returncalc(1)+calc(3)res=self.meta_interp(f,[])assertres==1000+1002self.check_resops(int_add=4)deftest_inline_in_portal(self):py.test.skip('in-progress')myjitdriver=JitDriver(greens=[],reds='auto')classMyRange(object):def__init__(self,n):self.cur=0self.n=ndef__iter__(self):returnself@myjitdriver.inline_in_portaldefnext(self):myjitdriver.jit_merge_point()ifself.cur==self.n:raiseStopIterationself.cur+=1returnself.curdefone():res=0foriinMyRange(10):res+=ireturnresdeftwo():res=0foriinMyRange(13):res+=i*2returnresdeff(n,m):res=one()*100res+=two()returnresexpected=f(21,5)res=self.meta_interp(f,[21,5])assertres==expectedself.check_resops(int_eq=4,int_add=8)self.check_trace_count(2)classTestLLWarmspot(WarmspotTests,LLJitMixin):CPUClass=runner.LLtypeCPUtype_system='lltype'classTestOOWarmspot(WarmspotTests,OOJitMixin):##CPUClass = runner.OOtypeCPUtype_system='ootype'classTestWarmspotDirect(object):defsetup_class(cls):frompypy.jit.metainterp.typesystemimportllhelperfrompypy.jit.codewriter.supportimportannotatefrompypy.jit.metainterp.warmspotimportWarmRunnerDescfrompypy.rpython.lltypesystem.rclassimportOBJECT,OBJECT_VTABLEfrompypy.rpython.lltypesystemimportlltype,llmemoryexc_vtable=lltype.malloc(OBJECT_VTABLE,immortal=True)cls.exc_vtable=exc_vtableclassFakeFailDescr(object):def__init__(self,no):self.no=nodefhandle_fail(self,metainterp_sd,jitdrivers_sd):no=self.noifno==0:raisemetainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3)ifno==1:raisemetainterp_sd.warmrunnerdesc.ContinueRunningNormally([0],[],[],[1],[],[])ifno==3:exc=lltype.malloc(OBJECT)exc.typeptr=exc_vtableraisemetainterp_sd.warmrunnerdesc.ExitFrameWithExceptionRef(metainterp_sd.cpu,lltype.cast_opaque_ptr(llmemory.GCREF,exc))assert0classFakeDescr:defas_vtable_size_descr(self):returnselfclassFakeCPU(object):supports_floats=Falsesupports_longlong=Falsesupports_singlefloats=Falsets=llhelpertranslate_support_code=Falsestats="stats"defget_fail_descr_number(self,d):return-1def__init__(self,*args,**kwds):passdefnodescr(self,*args,**kwds):returnFakeDescr()fielddescrof=nodescrcalldescrof=nodescrsizeof=nodescrdefget_fail_descr_from_number(self,no):returnFakeFailDescr(no)defmake_execute_token(self,*ARGS):return"not callable"driver=JitDriver(reds=['red'],greens=['green'])deff(green):red=0whilered<10:driver.can_enter_jit(red=red,green=green)driver.jit_merge_point(red=red,green=green)red+=1returnredrtyper=annotate(f,[0])FakeCPU.rtyper=rtypertranslator=rtyper.annotator.translatortranslator.config.translation.gc='hybrid'cls.desc=WarmRunnerDesc(translator,CPUClass=FakeCPU)deftest_call_helper(self):frompypy.rpython.llinterpimportLLException[jd]=self.desc.jitdrivers_sdassertjd._assembler_call_helper(0,0)==3assertjd._assembler_call_helper(1,0)==10try:jd._assembler_call_helper(3,0)exceptLLException,lle:assertlle[0]==self.exc_vtableelse:py.test.fail("DID NOT RAISE")