def make_vrefinfo(self): from pypy.jit.metainterp.virtualref import VirtualRefInfo class FakeWarmRunnerDesc: cpu = self.metainterp_sd.cpu self.metainterp_sd.virtualref_info = VirtualRefInfo(FakeWarmRunnerDesc)
def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, ProfilerClass=EmptyProfiler, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! self.set_translator(translator) self.memory_manager = memmgr.MemoryManager() self.build_cpu(CPUClass, **kwds) self.find_portals() self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd) if policy is None: policy = JitPolicy() policy.set_supports_floats(self.cpu.supports_floats) policy.set_supports_longlong(self.cpu.supports_longlong) policy.set_supports_singlefloats(self.cpu.supports_singlefloats) graphs = self.codewriter.find_all_graphs(policy) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) elif self.opt.listops: self.prejit_optimizations_minimal_inline(policy, graphs) self.build_meta_interp(ProfilerClass) self.make_args_specifications() # from pypy.jit.metainterp.virtualref import VirtualRefInfo vrefinfo = VirtualRefInfo(self) self.codewriter.setup_vrefinfo(vrefinfo) # self.hooks = policy.jithookiface self.make_virtualizable_infos() self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_functions() self.rewrite_jit_merge_points(policy) verbose = False # not self.cpu.translate_support_code self.rewrite_access_helpers() self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jits() self.rewrite_set_param() self.rewrite_force_virtual(vrefinfo) self.rewrite_force_quasi_immutable() self.add_finish() self.metainterp_sd.finish_setup(self.codewriter)
def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, optimizer=None, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! if policy is None: policy = JitPolicy() self.set_translator(translator) self.find_portal() self.make_leave_jit_graph() self.codewriter = codewriter.CodeWriter(self.rtyper) graphs = self.codewriter.find_all_graphs(self.portal_graph, self.leave_graph, policy, CPUClass.supports_floats) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) self.build_meta_interp(CPUClass, **kwds) self.make_args_specification() # from pypy.jit.metainterp.virtualref import VirtualRefInfo self.metainterp_sd.virtualref_info = VirtualRefInfo(self) if self.jitdriver.virtualizables: from pypy.jit.metainterp.virtualizable import VirtualizableInfo self.metainterp_sd.virtualizable_info = VirtualizableInfo(self) # self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_function() self.rewrite_jit_merge_point(policy) self.codewriter.generate_bytecode(self.metainterp_sd, self.portal_graph, self.leave_graph, self.portal_runner_ptr ) self.rewrite_can_enter_jit() self.rewrite_set_param() self.rewrite_force_virtual() self.add_finish() self.metainterp_sd.finish_setup(optimizer=optimizer)
class LLtypeMixin(object): type_system = 'lltype' def get_class_of_box(self, box): return box.getref(rclass.OBJECTPTR).typeptr node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable.name = rclass.alloc_array_name('node') node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable2.name = rclass.alloc_array_name('node2') node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2) cpu = runner.LLtypeCPU(None) NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed), ('floatval', lltype.Float), ('next', lltype.Ptr(NODE)))) NODE2 = lltype.GcStruct('NODE2', ('parent', NODE), ('other', lltype.Ptr(NODE))) node = lltype.malloc(NODE) node.parent.typeptr = node_vtable nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) myptr = nodebox.value myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(NODE)) nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodesize = cpu.sizeof(NODE) nodesize2 = cpu.sizeof(NODE2) valuedescr = cpu.fielddescrof(NODE, 'value') floatdescr = cpu.fielddescrof(NODE, 'floatval') nextdescr = cpu.fielddescrof(NODE, 'next') otherdescr = cpu.fielddescrof(NODE2, 'other') NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT), ('ref', lltype.Ptr(OBJECT))) nodeobj = lltype.malloc(NODEOBJ) nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj) refdescr = cpu.fielddescrof(NODEOBJ, 'ref') arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed)) floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float)) # a GcStruct not inheriting from OBJECT S = lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('b', lltype.Ptr(NODE))) ssize = cpu.sizeof(S) adescr = cpu.fielddescrof(S, 'a') bdescr = cpu.fielddescrof(S, 'b') sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))) arraydescr2 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(S))) T = lltype.GcStruct('TUPLE', ('c', lltype.Signed), ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE))))) tsize = cpu.sizeof(T) cdescr = cpu.fielddescrof(T, 'c') ddescr = cpu.fielddescrof(T, 'd') arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE))) U = lltype.GcStruct('U', ('parent', OBJECT), ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE))))) u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) u_vtable_adr = llmemory.cast_ptr_to_adr(u_vtable) usize = cpu.sizeof(U) onedescr = cpu.fielddescrof(U, 'one') FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [])) writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [adescr], [])) writearraydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [adescr], [arraydescr])) readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([adescr], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], forces_virtual_or_virtualizable=True)) class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though from pypy.jit.metainterp.virtualref import VirtualRefInfo class FakeWarmRunnerDesc: pass FakeWarmRunnerDesc.cpu = cpu vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc) virtualtokendescr = vrefinfo.descr_virtual_token virtualrefindexdescr = vrefinfo.descr_virtualref_index virtualforceddescr = vrefinfo.descr_forced jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) cpu.class_sizes = { cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE), cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2), cpu.cast_adr_to_int(u_vtable_adr): cpu.sizeof(U), cpu.cast_adr_to_int(jvr_vtable_adr): cpu.sizeof( vrefinfo.JIT_VIRTUAL_REF), } namespace = locals()
def finish_setup_for_interp_operations(self): self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) self.cw.setup_vrefinfo(self.vrefinfo)
class VRefTests: def finish_setup_for_interp_operations(self): self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) self.cw.setup_vrefinfo(self.vrefinfo) def test_rewrite_graphs(self): class X: pass def fn(): x = X() vref = virtual_ref(x) x1 = vref() # jit_force_virtual virtual_ref_finish(vref, x) # _get_jitcodes(self, self.CPUClass, fn, [], self.type_system) graph = self.all_graphs[0] assert graph.name == 'fn' self.vrefinfo.replace_force_virtual_with_call([graph]) # def check_call(op, fname): assert op.opname == 'direct_call' assert op.args[0].value._obj._name == fname # ops = [op for block, op in graph.iterblockops()] check_call(ops[-3], 'virtual_ref') check_call(ops[-2], 'force_virtual_if_necessary') check_call(ops[-1], 'virtual_ref_finish') def test_make_vref_simple(self): class X: pass class ExCtx: pass exctx = ExCtx() # def f(): x = X() exctx.topframeref = vref = virtual_ref(x) exctx.topframeref = vref_None virtual_ref_finish(vref, x) return 1 # self.interp_operations(f, []) self.check_operations_history( new_with_vtable=1, # X() virtual_ref=1, virtual_ref_finish=1) def test_make_vref_guard(self): if not isinstance(self, TestLLtype): py.test.skip("purely frontend test") # class FooBarError(Exception): pass class X: def __init__(self, n): self.n = n class ExCtx: _frame = None exctx = ExCtx() # @dont_look_inside def external(n): if exctx._frame is None: raise FooBarError if n > 100: return exctx.topframeref().n return n def enter(n): x = X(n + 10) exctx._frame = x exctx.topframeref = virtual_ref(x) def leave(): vref = exctx.topframeref exctx.topframeref = vref_None virtual_ref_finish(vref, exctx._frame) def f(n): enter(n) n = external(n) # ^^^ the point is that X() and the vref should be kept alive here leave() return n # res = self.interp_operations(f, [5]) assert res == 5 self.check_operations_history(virtual_ref=1, guard_not_forced=1) # ops = self.metainterp.staticdata.stats.loops[0].operations [guard_op ] = [op for op in ops if op.getopnum() == rop.GUARD_NOT_FORCED] bxs1 = [ box for box in guard_op.getfailargs() if str(box._getrepr_()).endswith('.X') ] assert len(bxs1) == 1 bxs2 = [ box for box in guard_op.getfailargs() if str(box._getrepr_()).endswith('JitVirtualRef') ] assert len(bxs2) == 1 JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # # try reloading from blackhole.py's point of view from pypy.jit.metainterp.resume import ResumeDataDirectReader cpu = self.metainterp.cpu cpu.get_latest_value_count = lambda: len(guard_op.getfailargs()) cpu.get_latest_value_int = lambda i: guard_op.getfailargs()[i].getint() cpu.get_latest_value_ref = lambda i: guard_op.getfailargs()[ i].getref_base() cpu.clear_latest_values = lambda count: None class FakeMetaInterpSd: callinfocollection = None FakeMetaInterpSd.cpu = cpu resumereader = ResumeDataDirectReader(FakeMetaInterpSd(), guard_op.getdescr()) vrefinfo = self.metainterp.staticdata.virtualref_info lst = [] vrefinfo.continue_tracing = lambda vref, virtual: \ lst.append((vref, virtual)) resumereader.consume_vref_and_vable(vrefinfo, None, None) del vrefinfo.continue_tracing assert len(lst) == 1 lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), lst[0][0]) # assert correct type # # try reloading from pyjitpl's point of view self.metainterp.rebuild_state_after_failure(guard_op.getdescr()) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value assert self.metainterp.virtualref_boxes[1].value == bxs2[0].value def test_make_vref_escape_after_finish(self): jitdriver = JitDriver(greens=[], reds=['n']) # class X: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def g(vref): # we cannot do anything with the vref after the call to finish() pass # def f(n): while n > 0: jitdriver.can_enter_jit(n=n) jitdriver.jit_merge_point(n=n) x = X() x.n = n exctx.topframeref = vref = virtual_ref(x) # here, 'x' should be virtual exctx.topframeref = vref_None virtual_ref_finish(vref, x) # 'x' and 'vref' can randomly escape after the call to # finish(). g(vref) n -= 1 return 1 # self.meta_interp(f, [10]) self.check_resops(new_with_vtable=2) # the vref self.check_aborted_count(0) def test_simple_all_removed(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) # self.meta_interp(f, [15]) self.check_resops(new_with_vtable=0, new_array=0) self.check_aborted_count(0) def test_simple_no_access(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): if n > 1000: return compute_unique_id(exctx.topframeref()) return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) # self.meta_interp(f, [15]) self.check_resops( new_with_vtable=2, # the vref: xy doesn't need to be forced new_array=0) # and neither xy.next1/2/3 self.check_aborted_count(0) def test_simple_force_always(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): m = exctx.topframeref().n assert m == n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) exctx.topframeref = vref_None # self.meta_interp(f, [15]) self.check_resops( new_with_vtable=4, # XY(), the vref new_array=6) # next1/2/3 self.check_aborted_count(0) def test_simple_force_sometimes(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): if n == 13: exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) exctx.topframeref = vref_None return exctx.m # res = self.meta_interp(f, [30]) assert res == 13 self.check_resops( new_with_vtable=2, # the vref, but not XY() new_array=0) # and neither next1/2/3 self.check_trace_count(1) self.check_aborted_count(0) def test_blackhole_forces(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) if n == 13: externalfn(n) n -= 1 exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) return exctx.m # res = self.meta_interp(f, [30]) assert res == 13 self.check_resops( new_with_vtable=0, # all virtualized in the n!=13 loop new_array=0) self.check_trace_count(1) self.check_aborted_count(0) def test_bridge_forces(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.next4 = lltype.malloc(A, 0) xy.next5 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) if n % 6 == 0: xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) externalfn(n) n -= 1 exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) xy.next4 = lltype.nullptr(A) xy.next5 = lltype.nullptr(A) virtual_ref_finish(vref, xy) return exctx.m # res = self.meta_interp(f, [72]) assert res == 6 self.check_trace_count(2) # the loop and the bridge self.check_resops( new_with_vtable=2, # loop: nothing; bridge: vref, xy new_array=2) # bridge: next4, next5 self.check_aborted_count(0) def test_jit_force_virtual_seen(self): myjitdriver = JitDriver(greens=[], reds=['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n exctx.topframeref = vref = virtual_ref(xy) xy.next1 = lltype.malloc(A, 0) n = exctx.topframeref().n - 1 xy.next1 = lltype.nullptr(A) exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return 1 # res = self.meta_interp(f, [15]) assert res == 1 self.check_resops( new_with_vtable=4, # vref, xy new_array=2) # next1 self.check_aborted_count(0) def test_recursive_call_1(self): myjitdriver = JitDriver(greens=[], reds=['n', 'rec', 'frame']) # class XY: pass class ExCtx: pass exctx = ExCtx() # def f(frame, n, reclevel): while n > 0: myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel) myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel) if reclevel == 0: return n xy = XY() exctx.topframeref = vref = virtual_ref(xy) m = f(xy, n, reclevel - 1) assert m == n n -= 1 exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return 2 def main(n, reclevel): return f(XY(), n, reclevel) # res = self.meta_interp(main, [15, 1]) assert res == main(15, 1) self.check_aborted_count(0) def test_recursive_call_2(self): myjitdriver = JitDriver(greens=[], reds=['n', 'rec', 'frame']) # class XY: n = 0 class ExCtx: pass exctx = ExCtx() # def f(frame, n, reclevel): while n > 0: myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel) myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel) frame.n += 1 xy = XY() xy.n = n exctx.topframeref = vref = virtual_ref(xy) if reclevel > 0: m = f(xy, frame.n, reclevel - 1) assert xy.n == m n -= 1 else: n -= 2 exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return frame.n def main(n, reclevel): return f(XY(), n, reclevel) # res = self.meta_interp(main, [10, 2]) assert res == main(10, 2) self.check_aborted_count(0) def test_alloc_virtualref_and_then_alloc_structure(self): myjitdriver = JitDriver(greens=[], reds=['n']) # class XY: pass class ExCtx: pass exctx = ExCtx() @dont_look_inside def escapexy(xy): print 'escapexy:', xy.n if xy.n % 5 == 0: vr = exctx.vr print 'accessing via vr:', vr() assert vr() is xy # def f(n): while n > 0: myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n vr = virtual_ref(xy) # force the virtualref to be allocated exctx.vr = vr # force xy to be allocated escapexy(xy) # clean up exctx.vr = vref_None virtual_ref_finish(vr, xy) n -= 1 return 1 # res = self.meta_interp(f, [15]) assert res == 1 self.check_resops(new_with_vtable=4) # vref, xy def test_cannot_use_invalid_virtualref(self): myjitdriver = JitDriver(greens=[], reds=['n']) # class XY: n = 0 # def fn(n): res = False while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n vref = virtual_ref(xy) virtual_ref_finish(vref, xy) vref() # raises InvalidVirtualRef when jitted n -= 1 return res # py.test.raises(InvalidVirtualRef, "fn(10)") py.test.raises(LLException, "self.meta_interp(fn, [10])") def test_call_virtualref_already_forced(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res']) # class XY: n = 0 # @dont_look_inside def force_it(vref, n): if n % 6 == 0: return vref().n return 0 def fn(n): res = 0 while n > 0: myjitdriver.can_enter_jit(n=n, res=res) myjitdriver.jit_merge_point(n=n, res=res) xy = XY() xy.n = n vref = virtual_ref(xy) force_it(vref, n) virtual_ref_finish(vref, xy) res += force_it( vref, n) # doesn't raise, because it was already forced n -= 1 return res # assert fn(10) == 6 res = self.meta_interp(fn, [10]) assert res == 6 def test_is_virtual(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) class X: pass @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) x = X() vref = virtual_ref(x) res1 = residual(vref) virtual_ref_finish(vref, x) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 1 def test_is_not_virtual_none(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) res1 = residual(vref_None) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 0 def test_is_not_virtual_non_none(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) class X: pass @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) x = X() res1 = residual(non_virtual_ref(x)) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 0
class VRefTests: def finish_setup_for_interp_operations(self): self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) self.cw.setup_vrefinfo(self.vrefinfo) def test_rewrite_graphs(self): class X: pass def fn(): x = X() vref = virtual_ref(x) x1 = vref() # jit_force_virtual virtual_ref_finish(vref, x) # _get_jitcodes(self, self.CPUClass, fn, [], self.type_system) graph = self.all_graphs[0] assert graph.name == 'fn' self.vrefinfo.replace_force_virtual_with_call([graph]) # def check_call(op, fname): assert op.opname == 'direct_call' assert op.args[0].value._obj._name == fname # ops = [op for block, op in graph.iterblockops()] check_call(ops[-3], 'virtual_ref') check_call(ops[-2], 'force_virtual_if_necessary') check_call(ops[-1], 'virtual_ref_finish') def test_make_vref_simple(self): class X: pass class ExCtx: pass exctx = ExCtx() # def f(): x = X() exctx.topframeref = vref = virtual_ref(x) exctx.topframeref = vref_None virtual_ref_finish(vref, x) return 1 # self.interp_operations(f, []) self.check_operations_history(new_with_vtable=1, # X() virtual_ref=1, virtual_ref_finish=1) def test_make_vref_guard(self): if not isinstance(self, TestLLtype): py.test.skip("purely frontend test") # class FooBarError(Exception): pass class X: def __init__(self, n): self.n = n class ExCtx: _frame = None exctx = ExCtx() # @dont_look_inside def external(n): if exctx._frame is None: raise FooBarError if n > 100: return exctx.topframeref().n return n def enter(n): x = X(n + 10) exctx._frame = x exctx.topframeref = virtual_ref(x) def leave(): vref = exctx.topframeref exctx.topframeref = vref_None virtual_ref_finish(vref, exctx._frame) def f(n): enter(n) n = external(n) # ^^^ the point is that X() and the vref should be kept alive here leave() return n # res = self.interp_operations(f, [5]) assert res == 5 self.check_operations_history(virtual_ref=1, guard_not_forced=1) # ops = self.metainterp.staticdata.stats.loops[0].operations [guard_op] = [op for op in ops if op.getopnum() == rop.GUARD_NOT_FORCED] bxs1 = [box for box in guard_op.getfailargs() if str(box._getrepr_()).endswith('.X')] assert len(bxs1) == 1 bxs2 = [box for box in guard_op.getfailargs() if str(box._getrepr_()).endswith('JitVirtualRef')] assert len(bxs2) == 1 JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # # try reloading from blackhole.py's point of view from pypy.jit.metainterp.resume import ResumeDataDirectReader cpu = self.metainterp.cpu cpu.get_latest_value_count = lambda : len(guard_op.getfailargs()) cpu.get_latest_value_int = lambda i:guard_op.getfailargs()[i].getint() cpu.get_latest_value_ref = lambda i:guard_op.getfailargs()[i].getref_base() cpu.clear_latest_values = lambda count: None class FakeMetaInterpSd: callinfocollection = None FakeMetaInterpSd.cpu = cpu resumereader = ResumeDataDirectReader(FakeMetaInterpSd(), guard_op.getdescr()) vrefinfo = self.metainterp.staticdata.virtualref_info lst = [] vrefinfo.continue_tracing = lambda vref, virtual: \ lst.append((vref, virtual)) resumereader.consume_vref_and_vable(vrefinfo, None, None) del vrefinfo.continue_tracing assert len(lst) == 1 lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), lst[0][0]) # assert correct type # # try reloading from pyjitpl's point of view self.metainterp.rebuild_state_after_failure(guard_op.getdescr()) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value assert self.metainterp.virtualref_boxes[1].value == bxs2[0].value def test_make_vref_escape_after_finish(self): jitdriver = JitDriver(greens = [], reds = ['n']) # class X: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def g(vref): # we cannot do anything with the vref after the call to finish() pass # def f(n): while n > 0: jitdriver.can_enter_jit(n=n) jitdriver.jit_merge_point(n=n) x = X() x.n = n exctx.topframeref = vref = virtual_ref(x) # here, 'x' should be virtual exctx.topframeref = vref_None virtual_ref_finish(vref, x) # 'x' and 'vref' can randomly escape after the call to # finish(). g(vref) n -= 1 return 1 # self.meta_interp(f, [10]) self.check_resops(new_with_vtable=2) # the vref self.check_aborted_count(0) def test_simple_all_removed(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) # self.meta_interp(f, [15]) self.check_resops(new_with_vtable=0, new_array=0) self.check_aborted_count(0) def test_simple_no_access(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): if n > 1000: return compute_unique_id(exctx.topframeref()) return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) # self.meta_interp(f, [15]) self.check_resops(new_with_vtable=2, # the vref: xy doesn't need to be forced new_array=0) # and neither xy.next1/2/3 self.check_aborted_count(0) def test_simple_force_always(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): m = exctx.topframeref().n assert m == n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) exctx.topframeref = vref_None # self.meta_interp(f, [15]) self.check_resops(new_with_vtable=4, # XY(), the vref new_array=6) # next1/2/3 self.check_aborted_count(0) def test_simple_force_sometimes(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): if n == 13: exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) n -= externalfn(n) xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) exctx.topframeref = vref_None return exctx.m # res = self.meta_interp(f, [30]) assert res == 13 self.check_resops(new_with_vtable=2, # the vref, but not XY() new_array=0) # and neither next1/2/3 self.check_trace_count(1) self.check_aborted_count(0) def test_blackhole_forces(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) if n == 13: externalfn(n) n -= 1 exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) virtual_ref_finish(vref, xy) return exctx.m # res = self.meta_interp(f, [30]) assert res == 13 self.check_resops(new_with_vtable=0, # all virtualized in the n!=13 loop new_array=0) self.check_trace_count(1) self.check_aborted_count(0) def test_bridge_forces(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # @dont_look_inside def externalfn(n): exctx.m = exctx.topframeref().n return 1 # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.next4 = lltype.malloc(A, 0) xy.next5 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) if n % 6 == 0: xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) externalfn(n) n -= 1 exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) xy.next4 = lltype.nullptr(A) xy.next5 = lltype.nullptr(A) virtual_ref_finish(vref, xy) return exctx.m # res = self.meta_interp(f, [72]) assert res == 6 self.check_trace_count(2) # the loop and the bridge self.check_resops(new_with_vtable=2, # loop: nothing; bridge: vref, xy new_array=2) # bridge: next4, next5 self.check_aborted_count(0) def test_jit_force_virtual_seen(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # A = lltype.GcArray(lltype.Signed) class XY: pass class ExCtx: pass exctx = ExCtx() # def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n exctx.topframeref = vref = virtual_ref(xy) xy.next1 = lltype.malloc(A, 0) n = exctx.topframeref().n - 1 xy.next1 = lltype.nullptr(A) exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return 1 # res = self.meta_interp(f, [15]) assert res == 1 self.check_resops(new_with_vtable=4, # vref, xy new_array=2) # next1 self.check_aborted_count(0) def test_recursive_call_1(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: pass class ExCtx: pass exctx = ExCtx() # def f(frame, n, reclevel): while n > 0: myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel) myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel) if reclevel == 0: return n xy = XY() exctx.topframeref = vref = virtual_ref(xy) m = f(xy, n, reclevel-1) assert m == n n -= 1 exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return 2 def main(n, reclevel): return f(XY(), n, reclevel) # res = self.meta_interp(main, [15, 1]) assert res == main(15, 1) self.check_aborted_count(0) def test_recursive_call_2(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: n = 0 class ExCtx: pass exctx = ExCtx() # def f(frame, n, reclevel): while n > 0: myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel) myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel) frame.n += 1 xy = XY() xy.n = n exctx.topframeref = vref = virtual_ref(xy) if reclevel > 0: m = f(xy, frame.n, reclevel-1) assert xy.n == m n -= 1 else: n -= 2 exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return frame.n def main(n, reclevel): return f(XY(), n, reclevel) # res = self.meta_interp(main, [10, 2]) assert res == main(10, 2) self.check_aborted_count(0) def test_alloc_virtualref_and_then_alloc_structure(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # class XY: pass class ExCtx: pass exctx = ExCtx() @dont_look_inside def escapexy(xy): print 'escapexy:', xy.n if xy.n % 5 == 0: vr = exctx.vr print 'accessing via vr:', vr() assert vr() is xy # def f(n): while n > 0: myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n vr = virtual_ref(xy) # force the virtualref to be allocated exctx.vr = vr # force xy to be allocated escapexy(xy) # clean up exctx.vr = vref_None virtual_ref_finish(vr, xy) n -= 1 return 1 # res = self.meta_interp(f, [15]) assert res == 1 self.check_resops(new_with_vtable=4) # vref, xy def test_cannot_use_invalid_virtualref(self): myjitdriver = JitDriver(greens = [], reds = ['n']) # class XY: n = 0 # def fn(n): res = False while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n vref = virtual_ref(xy) virtual_ref_finish(vref, xy) vref() # raises InvalidVirtualRef when jitted n -= 1 return res # py.test.raises(InvalidVirtualRef, "fn(10)") py.test.raises(LLException, "self.meta_interp(fn, [10])") def test_call_virtualref_already_forced(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'res']) # class XY: n = 0 # @dont_look_inside def force_it(vref, n): if n % 6 == 0: return vref().n return 0 def fn(n): res = 0 while n > 0: myjitdriver.can_enter_jit(n=n, res=res) myjitdriver.jit_merge_point(n=n, res=res) xy = XY() xy.n = n vref = virtual_ref(xy) force_it(vref, n) virtual_ref_finish(vref, xy) res += force_it(vref, n) # doesn't raise, because it was already forced n -= 1 return res # assert fn(10) == 6 res = self.meta_interp(fn, [10]) assert res == 6 def test_is_virtual(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) class X: pass @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) x = X() vref = virtual_ref(x) res1 = residual(vref) virtual_ref_finish(vref, x) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 1 def test_is_not_virtual_none(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) res1 = residual(vref_None) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 0 def test_is_not_virtual_non_none(self): myjitdriver = JitDriver(greens=[], reds=['n', 'res1']) class X: pass @dont_look_inside def residual(vref): return vref.virtual # def f(n): res1 = -42 while n > 0: myjitdriver.jit_merge_point(n=n, res1=res1) x = X() res1 = residual(non_virtual_ref(x)) n -= 1 return res1 # res = self.meta_interp(f, [10]) assert res == 0
class LLtypeMixin(object): type_system = 'lltype' def get_class_of_box(self, box): return box.getref(rclass.OBJECTPTR).typeptr node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable.name = rclass.alloc_array_name('node') node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable2.name = rclass.alloc_array_name('node2') node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2) cpu = runner.LLtypeCPU(None) NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed), ('floatval', lltype.Float), ('next', lltype.Ptr(NODE)))) NODE2 = lltype.GcStruct('NODE2', ('parent', NODE), ('other', lltype.Ptr(NODE))) node = lltype.malloc(NODE) node.parent.typeptr = node_vtable node2 = lltype.malloc(NODE2) node2.parent.parent.typeptr = node_vtable2 nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) myptr = nodebox.value myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(NODE)) nullptr = lltype.nullptr(llmemory.GCREF.TO) nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node2)) nodesize = cpu.sizeof(NODE) nodesize2 = cpu.sizeof(NODE2) valuedescr = cpu.fielddescrof(NODE, 'value') floatdescr = cpu.fielddescrof(NODE, 'floatval') nextdescr = cpu.fielddescrof(NODE, 'next') otherdescr = cpu.fielddescrof(NODE2, 'other') accessor = FieldListAccessor() accessor.initialize(None, {'inst_field': IR_QUASIIMMUTABLE}) QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed), ('mutate_field', rclass.OBJECTPTR), hints={'immutable_fields': accessor}) quasisize = cpu.sizeof(QUASI) quasi = lltype.malloc(QUASI, immortal=True) quasi.inst_field = -4247 quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field') quasibox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, quasi)) quasiimmutdescr = QuasiImmutDescr(cpu, quasibox, quasifielddescr, cpu.fielddescrof(QUASI, 'mutate_field')) NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT), ('ref', lltype.Ptr(OBJECT))) nodeobj = lltype.malloc(NODEOBJ) nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj) refdescr = cpu.fielddescrof(NODEOBJ, 'ref') INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT), ('intval', lltype.Signed)) INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT), ('intval', lltype.Signed), hints={'immutable': True}) intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval') immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval') PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT), ('ptrval', lltype.Ptr(OBJECT)), hints={'immutable': True}) ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval') arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed)) floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float)) # a GcStruct not inheriting from OBJECT S = lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('b', lltype.Ptr(NODE))) ssize = cpu.sizeof(S) adescr = cpu.fielddescrof(S, 'a') bdescr = cpu.fielddescrof(S, 'b') sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))) arraydescr2 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(S))) T = lltype.GcStruct('TUPLE', ('c', lltype.Signed), ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE))))) tsize = cpu.sizeof(T) cdescr = cpu.fielddescrof(T, 'c') ddescr = cpu.fielddescrof(T, 'd') arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE))) U = lltype.GcStruct('U', ('parent', OBJECT), ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE))))) u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) u_vtable_adr = llmemory.cast_ptr_to_adr(u_vtable) usize = cpu.sizeof(U) onedescr = cpu.fielddescrof(U, 'one') FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL) nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [])) writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [adescr], [])) writearraydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [adescr], [arraydescr])) readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([adescr], [], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], [], EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE, can_invalidate=True)) arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [arraydescr], [], [arraydescr], EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) # array of structs (complex data) complexarray = lltype.GcArray( lltype.Struct("complex", ("real", lltype.Float), ("imag", lltype.Float), ) ) complexarraydescr = cpu.arraydescrof(complexarray) complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), ('strequaldescr', 'OS_STR_EQUAL'), ('streq_slice_checknull_descr', 'OS_STREQ_SLICE_CHECKNULL'), ('streq_slice_nonnull_descr', 'OS_STREQ_SLICE_NONNULL'), ('streq_slice_char_descr', 'OS_STREQ_SLICE_CHAR'), ('streq_nonnull_descr', 'OS_STREQ_NONNULL'), ('streq_nonnull_char_descr', 'OS_STREQ_NONNULL_CHAR'), ('streq_checknull_char_descr', 'OS_STREQ_CHECKNULL_CHAR'), ('streq_lengthok_descr', 'OS_STREQ_LENGTHOK'), ]: _oopspecindex = getattr(EffectInfo, _os) locals()[_name] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=_oopspecindex)) # _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI')) locals()[_name.replace('str', 'unicode')] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=_oopspecindex)) s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE)) # class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though from pypy.jit.metainterp.virtualref import VirtualRefInfo class FakeWarmRunnerDesc: pass FakeWarmRunnerDesc.cpu = cpu vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc) virtualtokendescr = vrefinfo.descr_virtual_token virtualforceddescr = vrefinfo.descr_forced jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) register_known_gctype(cpu, node_vtable, NODE) register_known_gctype(cpu, node_vtable2, NODE2) register_known_gctype(cpu, u_vtable, U) register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF) register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT) register_known_gctype(cpu, intobj_immut_vtable, INTOBJ_IMMUT) register_known_gctype(cpu, ptrobj_immut_vtable, PTROBJ_IMMUT) namespace = locals()
def finish_metainterp_for_interp_operations(self, metainterp): self.vrefinfo = VirtualRefInfo(metainterp.staticdata.state) metainterp.staticdata.virtualref_info = self.vrefinfo