def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue, custom_eq_hash=None): self.rtyper = rtyper self.DICT = lltype.GcForwardReference() self.lowleveltype = lltype.Ptr(self.DICT) self.custom_eq_hash = custom_eq_hash is not None if not isinstance(key_repr, rmodel.Repr): # not computed yet, done by setup() assert callable(key_repr) self._key_repr_computer = key_repr else: self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr) if not isinstance(value_repr, rmodel.Repr): # not computed yet, done by setup() assert callable(value_repr) self._value_repr_computer = value_repr else: self.external_value_repr, self.value_repr = self.pickrepr( value_repr) self.dictkey = dictkey self.dictvalue = dictvalue self.dict_cache = {} self._custom_eq_hash_repr = custom_eq_hash
def setup_class(cls): cls.STRUCT = lltype.GcStruct("dummy", ("foo", lltype.Signed)) cls.fielddesc = getfielddesc(cls.STRUCT, "foo") FORWARD = lltype.GcForwardReference() cls.NESTEDSTRUCT = lltype.GcStruct('dummy', ("foo", lltype.Signed), ('x', lltype.Ptr(FORWARD))) FORWARD.become(cls.NESTEDSTRUCT)
def define_dump_rpy_heap(self): U = lltype.GcForwardReference() U.become(lltype.GcStruct('U', ('next', lltype.Ptr(U)), ('x', lltype.Signed))) S = lltype.GcStruct('S', ('u', lltype.Ptr(U))) A = lltype.GcArray(lltype.Ptr(S)) filename1 = self.filename1_dump filename2 = self.filename2_dump def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) s.u.next = lltype.malloc(U) s.u.next.next = lltype.malloc(U) a = lltype.malloc(A, 1000) s2 = lltype.malloc(S) # fd1 = os.open(filename1, os.O_WRONLY | os.O_CREAT, 0666) fd2 = os.open(filename2, os.O_WRONLY | os.O_CREAT, 0666) rgc.dump_rpy_heap(fd1) rgc.dump_rpy_heap(fd2) # try twice in a row keepalive_until_here(s2) keepalive_until_here(s) keepalive_until_here(a) os.close(fd1) os.close(fd2) return 0 return fn
def define_write_typeids_z(self): U = lltype.GcForwardReference() U.become(lltype.GcStruct('U', ('next', lltype.Ptr(U)), ('x', lltype.Signed))) S = lltype.GcStruct('S', ('u', lltype.Ptr(U))) A = lltype.GcArray(lltype.Ptr(S)) filename = self.filename_dump_typeids_z open_flags = os.O_WRONLY | os.O_CREAT | getattr(os, 'O_BINARY', 0) def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) s.u.next = lltype.malloc(U) s.u.next.next = lltype.malloc(U) a = lltype.malloc(A, 1000) s2 = lltype.malloc(S) # p = rgc.get_typeids_z() s = ''.join([p[i] for i in range(len(p))]) fd = os.open(filename, open_flags, 0666) os.write(fd, s) os.close(fd) return 0 return fn
def test_recursive_structure(): F = lltype.GcForwardReference() S = lltype.GcStruct('abc', ('x', lltype.Ptr(F))) F.become(S) def f(): s1 = lltype.malloc(S) s2 = lltype.malloc(S) s1.x = s2 t, transformer = rtype_and_transform( f, [], RefcountingGCTransformer, check=False)
def get_shadowstackref(gctransformer): if hasattr(gctransformer, '_SHADOWSTACKREF'): return gctransformer._SHADOWSTACKREF SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference()) SHADOWSTACKREF = lltype.GcStruct( 'ShadowStackRef', ('base', llmemory.Address), ('top', llmemory.Address), ('context', llmemory.Address), #('fullstack', lltype.Bool), rtti=True) SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF) translator = gctransformer.translator if hasattr(translator, '_jit2gc'): gc = gctransformer.gcdata.gc root_iterator = translator._jit2gc['root_iterator'] def customtrace(obj, prev): obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR) if not prev: root_iterator.context = obj.context next = obj.base else: next = prev + sizeofaddr return root_iterator.next(gc, next, obj.top) else: def customtrace(obj, prev): # a simple but not JIT-ready version if not prev: next = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).base else: next = prev + sizeofaddr if next == llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).top: next = llmemory.NULL return next CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr) gctransformer._SHADOWSTACKREF = SHADOWSTACKREF return SHADOWSTACKREF
def define_assume_young_pointers(cls): from pypy.rlib import rgc S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', ('x', lltype.Signed), ('prev', lltype.Ptr(S)), ('next', lltype.Ptr(S)))) s0 = lltype.malloc(S, immortal=True) def f(): s = lltype.malloc(S) s.x = 42 llop.bare_setfield(lltype.Void, s0, void('next'), s) llop.gc_assume_young_pointers(lltype.Void, llmemory.cast_ptr_to_adr(s0)) rgc.collect(0) return s0.next.x def cleanup(): s0.next = lltype.nullptr(S) return f, cleanup, None
def define_tree_cloning(cls): import os # this makes a tree of calls. Each leaf stores its path (a linked # list) in 'result'. Paths are mutated in-place but the leaves don't # see each other's mutations because of x_clone. STUFF = lltype.FixedSizeArray(lltype.Signed, 21) NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('node', ('index', lltype.Signed), ('counter', lltype.Signed), ('next', lltype.Ptr(NODE)), ('use_some_space', STUFF))) PATHARRAY = lltype.GcArray(lltype.Ptr(NODE)) clonedata = lltype.malloc(X_CLONE) def clone(node): # that's for testing if the test is correct... if not node: return node newnode = lltype.malloc(NODE) newnode.index = node.index newnode.counter = node.counter newnode.next = clone(node.next) return newnode def do_call(result, path, index, remaining_depth): # clone the while path clonedata.gcobjectptr = lltype.cast_opaque_ptr(llmemory.GCREF, path) clonedata.pool = lltype.nullptr(X_POOL) llop.gc_x_clone(lltype.Void, clonedata) # install the new pool as the current one parentpool = llop.gc_x_swap_pool(X_POOL_PTR, clonedata.pool) path = lltype.cast_opaque_ptr(lltype.Ptr(NODE), clonedata.gcobjectptr) # The above should have the same effect as: # path = clone(path) # bump all the path node counters by one p = path while p: p.counter += 1 p = p.next if remaining_depth == 0: llop.debug_print(lltype.Void, "setting", index, "with", path) result[index] = path # leaf else: node = lltype.malloc(NODE) node.index = index * 2 node.counter = 0 node.next = path do_call(result, node, index * 2, remaining_depth - 1) node.index += 1 # mutation! do_call(result, node, index * 2 + 1, remaining_depth - 1) # restore the parent pool llop.gc_x_swap_pool(X_POOL_PTR, parentpool) def check(path, index, level, depth): if level == depth: assert index == 0 assert not path else: assert path.index == index assert path.counter == level + 1 check(path.next, index >> 1, level + 1, depth) def func(depth, dummy): result = lltype.malloc(PATHARRAY, 1 << depth) os.write(2, 'building tree... ') do_call(result, lltype.nullptr(NODE), 0, depth) os.write(2, 'checking tree... ') #from pypy.rpython.lltypesystem.lloperation import llop #llop.debug_view(lltype.Void, result, # llop.gc_x_size_header(lltype.Signed)) for i in range(1 << depth): check(result[i], i, 0, depth) os.write(2, 'ok\n') return 1 return func
from pypy.jit.timeshifter.test.test_portal import PortalTest, P_OOPSPEC from pypy.jit.timeshifter.test.test_timeshift import StopAtXPolicy from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR from pypy.rlib.jit import hint import py S = lltype.GcStruct('s', ('a', lltype.Signed), ('b', lltype.Signed)) PS = lltype.Ptr(S) XY = lltype.GcForwardReference() GETTER = lambda STRUC: lltype.Ptr( lltype.FuncType([lltype.Ptr(STRUC)], lltype.Signed)) SETTER = lambda STRUC: lltype.Ptr( lltype.FuncType([lltype.Ptr(STRUC), lltype.Signed], lltype.Void)) def getset(name): def get(obj): access = obj.vable_access if access: return getattr(access, 'get_' + name)(obj) else: return getattr(obj, name) get.oopspec = 'vable.get_%s(obj)' % name def set(obj, value): access = obj.vable_access if access: return getattr(access, 'set_' + name)(obj, value)
def _get_NODE(self): NODE = lltype.GcForwardReference() NODE.become( lltype.GcStruct('NODE', ('value', lltype.Signed), ('next', lltype.Ptr(NODE)))) return NODE
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()
elif T is lltype.Float: return lltype.Float elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]: return lltype.SignedLongLong elif T is llmemory.Address: return llmemory.Address elif isinstance(T, lltype.Primitive): return lltype.Signed else: raise Exception("don't know about %r" % (T,)) # ____________________________________________________________ # structures for saved frame states STATE_HEADER = lltype.GcStruct('state_header', ('f_back', lltype.Ptr(lltype.GcForwardReference())), ('f_restart', lltype.Signed), ('f_depth', lltype.Signed)) STATE_HEADER.f_back.TO.become(STATE_HEADER) null_state = lltype.nullptr(STATE_HEADER) OPAQUE_STATE_HEADER_PTR = rstack.OPAQUE_STATE_HEADER_PTR def make_state_header_type(name, *fields): return lltype.GcStruct(name, ('header', STATE_HEADER), *fields) # ____________________________________________________________
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()
class TestRegallocGcIntegration(BaseTestRegalloc): cpu = CPU(None, None) cpu.gc_ll_descr = MockGcDescr(False) cpu.setup_once() S = lltype.GcForwardReference() S.become( lltype.GcStruct('S', ('field', lltype.Ptr(S)), ('int', lltype.Signed))) fielddescr = cpu.fielddescrof(S, 'field') struct_ptr = lltype.malloc(S) struct_ref = lltype.cast_opaque_ptr(llmemory.GCREF, struct_ptr) child_ptr = lltype.nullptr(S) struct_ptr.field = child_ptr descr0 = cpu.fielddescrof(S, 'int') ptr0 = struct_ref targettoken = TargetToken() namespace = locals().copy() def test_basic(self): ops = ''' [p0] p1 = getfield_gc(p0, descr=fielddescr) finish(p1) ''' self.interpret(ops, [self.struct_ptr]) assert not self.getptr(0, lltype.Ptr(self.S)) def test_rewrite_constptr(self): ops = ''' [] p1 = getfield_gc(ConstPtr(struct_ref), descr=fielddescr) finish(p1) ''' self.interpret(ops, []) assert not self.getptr(0, lltype.Ptr(self.S)) def test_bug_0(self): ops = ''' [i0, i1, i2, i3, i4, i5, i6, i7, i8] label(i0, i1, i2, i3, i4, i5, i6, i7, i8, descr=targettoken) guard_value(i2, 1) [i2, i3, i4, i5, i6, i7, i0, i1, i8] guard_class(i4, 138998336) [i4, i5, i6, i7, i0, i1, i8] i11 = getfield_gc(i4, descr=descr0) guard_nonnull(i11) [i4, i5, i6, i7, i0, i1, i11, i8] i13 = getfield_gc(i11, descr=descr0) guard_isnull(i13) [i4, i5, i6, i7, i0, i1, i11, i8] i15 = getfield_gc(i4, descr=descr0) i17 = int_lt(i15, 0) guard_false(i17) [i4, i5, i6, i7, i0, i1, i11, i15, i8] i18 = getfield_gc(i11, descr=descr0) i19 = int_ge(i15, i18) guard_false(i19) [i4, i5, i6, i7, i0, i1, i11, i15, i8] i20 = int_lt(i15, 0) guard_false(i20) [i4, i5, i6, i7, i0, i1, i11, i15, i8] i21 = getfield_gc(i11, descr=descr0) i22 = getfield_gc(i11, descr=descr0) i23 = int_mul(i15, i22) i24 = int_add(i21, i23) i25 = getfield_gc(i4, descr=descr0) i27 = int_add(i25, 1) setfield_gc(i4, i27, descr=descr0) i29 = getfield_raw(144839744, descr=descr0) i31 = int_and(i29, -2141192192) i32 = int_is_true(i31) guard_false(i32) [i4, i6, i7, i0, i1, i24] i33 = getfield_gc(i0, descr=descr0) guard_value(i33, ConstPtr(ptr0)) [i4, i6, i7, i0, i1, i33, i24] jump(i0, i1, 1, 17, i4, ConstPtr(ptr0), i6, i7, i24, descr=targettoken) ''' self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0, 0], run=False)
class BlockBuilderMixin(object): _mixin_ = True # A base class to generate assembler. It is equivalent to just a list # of chars, but it is potentially more efficient for that usage. # It works by allocating the assembler SUBBLOCK_SIZE bytes at a time. # Ideally, this number should be a power of two that fits the GC's most # compact allocation scheme (which is so far 35 * WORD for minimark.py). WORD = LONG_BIT // 8 SUBBLOCK_SIZE = 32 * WORD SUBBLOCK_PTR = lltype.Ptr(lltype.GcForwardReference()) SUBBLOCK = lltype.GcStruct( 'SUBBLOCK', ('prev', SUBBLOCK_PTR), ('data', lltype.FixedSizeArray(lltype.Char, SUBBLOCK_SIZE))) SUBBLOCK_PTR.TO.become(SUBBLOCK) gcroot_markers = None def __init__(self, translated=None): if translated is None: translated = we_are_translated() if translated: self.init_block_builder() else: self._become_a_plain_block_builder() def init_block_builder(self): self._cursubblock = lltype.nullptr(self.SUBBLOCK) self._baserelpos = -self.SUBBLOCK_SIZE self._make_new_subblock() def _make_new_subblock(self): nextsubblock = lltype.malloc(self.SUBBLOCK) nextsubblock.prev = self._cursubblock self._cursubblock = nextsubblock self._cursubindex = 0 self._baserelpos += self.SUBBLOCK_SIZE _make_new_subblock._dont_inline_ = True def writechar(self, char): index = self._cursubindex if index == self.SUBBLOCK_SIZE: self._make_new_subblock() index = 0 self._cursubblock.data[index] = char self._cursubindex = index + 1 def overwrite(self, index, char): assert 0 <= index < self.get_relative_pos() block = self._cursubblock index -= self._baserelpos while index < 0: block = block.prev index += self.SUBBLOCK_SIZE block.data[index] = char def get_relative_pos(self): return self._baserelpos + self._cursubindex def copy_to_raw_memory(self, addr): # indirection for _become_a_plain_block_builder() and for subclasses self._copy_to_raw_memory(addr) def _copy_to_raw_memory(self, addr): block = self._cursubblock blocksize = self._cursubindex targetindex = self._baserelpos while targetindex >= 0: dst = rffi.cast(rffi.CCHARP, addr + targetindex) for j in range(blocksize): dst[j] = block.data[j] block = block.prev blocksize = self.SUBBLOCK_SIZE targetindex -= self.SUBBLOCK_SIZE assert not block def _dump(self, addr, logname, backend=None): debug_start(logname) if have_debug_prints(): # if backend is not None: debug_print('BACKEND', backend) # from pypy.jit.backend.hlinfo import highleveljitinfo if highleveljitinfo.sys_executable: debug_print('SYS_EXECUTABLE', highleveljitinfo.sys_executable) # HEX = '0123456789ABCDEF' dump = [] src = rffi.cast(rffi.CCHARP, addr) for p in range(self.get_relative_pos()): o = ord(src[p]) dump.append(HEX[o >> 4]) dump.append(HEX[o & 15]) debug_print( 'CODE_DUMP', '@%x' % addr, '+0 ', # backwards compatibility ''.join(dump)) # debug_stop(logname) def materialize(self, asmmemmgr, allblocks, gcrootmap=None): size = self.get_relative_pos() malloced = asmmemmgr.malloc(size, size) allblocks.append(malloced) rawstart = malloced[0] self.copy_to_raw_memory(rawstart) if self.gcroot_markers is not None: assert gcrootmap is not None for pos, mark in self.gcroot_markers: gcrootmap.put(rawstart + pos, mark) return rawstart def _become_a_plain_block_builder(self): # hack purely for speed of tests self._data = [] self.writechar = self._data.append self.overwrite = self._data.__setitem__ self.get_relative_pos = self._data.__len__ def plain_copy_to_raw_memory(addr): dst = rffi.cast(rffi.CCHARP, addr) for i, c in enumerate(self._data): dst[i] = c self._copy_to_raw_memory = plain_copy_to_raw_memory def insert_gcroot_marker(self, mark): if self.gcroot_markers is None: self.gcroot_markers = [] self.gcroot_markers.append((self.get_relative_pos(), mark))
class LLtypeMixin(object): type_system = 'lltype' def get_class_of_box(self, box): from pypy.rpython.lltypesystem import rclass return box.getref(rclass.OBJECTPTR).typeptr node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True) 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') 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') 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) } namespace = locals()
instantiating them and asking them to allocate memory by calling their methods directly. The tests need to maintain by hand what the GC should see as the list of roots (stack and prebuilt objects). """ # XXX VERY INCOMPLETE, low coverage import py from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder from pypy.rlib.rarithmetic import LONG_BIT, is_valid_int WORD = LONG_BIT // 8 ADDR_ARRAY = lltype.Array(llmemory.Address) S = lltype.GcForwardReference() S.become( lltype.GcStruct('S', ('x', lltype.Signed), ('prev', lltype.Ptr(S)), ('next', lltype.Ptr(S)))) RAW = lltype.Struct('RAW', ('p', lltype.Ptr(S)), ('q', lltype.Ptr(S))) VAR = lltype.GcArray(lltype.Ptr(S)) VARNODE = lltype.GcStruct('VARNODE', ('a', lltype.Ptr(VAR))) class DirectRootWalker(object): def __init__(self, tester): self.tester = tester def walk_roots(self, collect_stack_root, collect_static_in_prebuilt_nongc, collect_static_in_prebuilt_gc): gc = self.tester.gc
return lltype.Float elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]: return lltype.SignedLongLong elif T is llmemory.Address: return llmemory.Address elif isinstance(T, lltype.Primitive): return lltype.Signed else: raise Exception("don't know about %r" % (T, )) # ____________________________________________________________ # structures for saved frame states STATE_HEADER = lltype.GcStruct( 'state_header', ('f_back', lltype.Ptr(lltype.GcForwardReference())), ('f_restart', lltype.Signed)) STATE_HEADER.f_back.TO.become(STATE_HEADER) null_state = lltype.nullptr(STATE_HEADER) OPAQUE_STATE_HEADER_PTR = rstack.OPAQUE_STATE_HEADER_PTR def make_state_header_type(name, *fields): return lltype.GcStruct(name, ('header', STATE_HEADER), *fields) # ____________________________________________________________ # master array giving information about the restart points # (STATE_HEADER.frameinfo is an index into this array)