WEAKREF = lltype.GcStruct("weakref", ("weakptr", llmemory.Address)) WEAKREFPTR = lltype.Ptr(WEAKREF) sizeof_weakref = llmemory.sizeof(WEAKREF) empty_weakref = lltype.malloc(WEAKREF, immortal=True) empty_weakref.weakptr = llmemory.NULL weakptr_offset = llmemory.offsetof(WEAKREF, "weakptr") def ll_weakref_deref(wref): wref = llmemory.cast_weakrefptr_to_ptr(WEAKREFPTR, wref) return wref.weakptr def convert_weakref_to(targetptr): # Prebuilt weakrefs don't really need to be weak at all, # but we need to emulate the structure expected by ll_weakref_deref(). if not targetptr: return empty_weakref else: link = lltype.malloc(WEAKREF, immortal=True) link.weakptr = llmemory.cast_ptr_to_adr(targetptr) return link ########## finalizers ########## FIN_TRIGGER_FUNC = lltype.FuncType([], lltype.Void) FIN_HANDLER_ARRAY = lltype.Array(('deque', llmemory.Address), ('trigger', lltype.Ptr(FIN_TRIGGER_FUNC)))
class GCData(object): """The GC information tables, and the query functions that the GC calls to decode their content. The encoding of this information is done by encode_type_shape(). These two places should be in sync, obviously, but in principle no other code should depend on the details of the encoding in TYPE_INFO. """ _alloc_flavor_ = 'raw' OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed) # A CUSTOM_FUNC is either a destructor, or a custom tracer. # A destructor is called when the object is about to be freed. # A custom tracer (CT) enumerates the addresses that contain GCREFs. # Both are called with the address of the object as only argument. # They're embedded in a struct that has raw_memory_offset as another # argument, which is only valid if T_HAS_MEMORY_PRESSURE is set CUSTOM_FUNC = lltype.FuncType([llmemory.Address], lltype.Void) CUSTOM_FUNC_PTR = lltype.Ptr(CUSTOM_FUNC) CUSTOM_DATA_STRUCT = lltype.Struct( 'custom_data', ('customfunc', CUSTOM_FUNC_PTR), ('memory_pressure_offset', lltype.Signed), # offset to where the amount # of owned memory pressure is stored ) CUSTOM_DATA_STRUCT_PTR = lltype.Ptr(CUSTOM_DATA_STRUCT) # structure describing the layout of a typeid TYPE_INFO = lltype.Struct( "type_info", ("infobits", lltype.Signed), # combination of the T_xxx consts ("customdata", CUSTOM_DATA_STRUCT_PTR), ("fixedsize", lltype.Signed), ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), hints={'immutable': True}, ) VARSIZE_TYPE_INFO = lltype.Struct( "varsize_type_info", ("header", TYPE_INFO), ("varitemsize", lltype.Signed), ("ofstovar", lltype.Signed), ("ofstolength", lltype.Signed), ("varofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), hints={'immutable': True}, ) TYPE_INFO_PTR = lltype.Ptr(TYPE_INFO) VARSIZE_TYPE_INFO_PTR = lltype.Ptr(VARSIZE_TYPE_INFO) def __init__(self, type_info_group): assert isinstance(type_info_group, llgroup.group) self.type_info_group = type_info_group self.type_info_group_ptr = type_info_group._as_ptr() def get(self, typeid): res = llop.get_group_member(GCData.TYPE_INFO_PTR, self.type_info_group_ptr, typeid) _check_valid_type_info(res) return res def get_varsize(self, typeid): res = llop.get_group_member(GCData.VARSIZE_TYPE_INFO_PTR, self.type_info_group_ptr, typeid) _check_valid_type_info_varsize(res) return res def q_is_varsize(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_IS_VARSIZE) != 0 def q_has_gcptr_in_varsize(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_HAS_GCPTR_IN_VARSIZE) != 0 def q_has_gcptr(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_HAS_GCPTR) != 0 def q_is_gcarrayofgcptr(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_IS_GCARRAY_OF_GCPTR) != 0 def q_cannot_pin(self, typeid): typeinfo = self.get(typeid) ANY = (T_HAS_GCPTR | T_IS_WEAKREF) return (typeinfo.infobits & ANY) != 0 or bool(typeinfo.customdata) def q_finalizer_handlers(self): adr = self.finalizer_handlers # set from framework.py or gcwrapper.py return llmemory.cast_adr_to_ptr(adr, lltype.Ptr(FIN_HANDLER_ARRAY)) def q_destructor_or_custom_trace(self, typeid): if not self.get(typeid).customdata: return lltype.nullptr(GCData.CUSTOM_FUNC_PTR.TO) return self.get(typeid).customdata.customfunc def q_is_old_style_finalizer(self, typeid): typeinfo = self.get(typeid) return (typeinfo.infobits & T_HAS_OLDSTYLE_FINALIZER) != 0 def q_offsets_to_gc_pointers(self, typeid): return self.get(typeid).ofstoptrs def q_fixed_size(self, typeid): return self.get(typeid).fixedsize def q_varsize_item_sizes(self, typeid): return self.get_varsize(typeid).varitemsize def q_varsize_offset_to_variable_part(self, typeid): return self.get_varsize(typeid).ofstovar def q_varsize_offset_to_length(self, typeid): return self.get_varsize(typeid).ofstolength def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid): return self.get_varsize(typeid).varofstoptrs def q_weakpointer_offset(self, typeid): infobits = self.get(typeid).infobits if infobits & T_IS_WEAKREF: return weakptr_offset return -1 def q_member_index(self, typeid): infobits = self.get(typeid).infobits return infobits & T_MEMBER_INDEX def q_is_rpython_class(self, typeid): infobits = self.get(typeid).infobits return infobits & T_IS_RPYTHON_INSTANCE != 0 def q_has_custom_trace(self, typeid): infobits = self.get(typeid).infobits return infobits & T_HAS_CUSTOM_TRACE != 0 def q_fast_path_tracing(self, typeid): # return True if none of the flags T_HAS_GCPTR_IN_VARSIZE, # T_IS_GCARRAY_OF_GCPTR or T_HAS_CUSTOM_TRACE is set T_ANY_SLOW_FLAG = (T_HAS_GCPTR_IN_VARSIZE | T_IS_GCARRAY_OF_GCPTR | T_HAS_CUSTOM_TRACE) infobits = self.get(typeid).infobits return infobits & T_ANY_SLOW_FLAG == 0 def q_has_memory_pressure(self, typeid): infobits = self.get(typeid).infobits return infobits & T_HAS_MEMORY_PRESSURE != 0 def q_get_memory_pressure_ofs(self, typeid): infobits = self.get(typeid).infobits assert infobits & T_HAS_MEMORY_PRESSURE != 0 return self.get(typeid).customdata.memory_pressure_offset def set_query_functions(self, gc): gc.set_query_functions( self.q_is_varsize, self.q_has_gcptr_in_varsize, self.q_is_gcarrayofgcptr, self.q_finalizer_handlers, self.q_destructor_or_custom_trace, self.q_is_old_style_finalizer, self.q_offsets_to_gc_pointers, self.q_fixed_size, self.q_varsize_item_sizes, self.q_varsize_offset_to_variable_part, self.q_varsize_offset_to_length, self.q_varsize_offsets_to_gcpointers_in_var_part, self.q_weakpointer_offset, self.q_member_index, self.q_is_rpython_class, self.q_has_custom_trace, self.q_fast_path_tracing, self.q_has_gcptr, self.q_cannot_pin, self.q_has_memory_pressure, self.q_get_memory_pressure_ofs) def _has_got_custom_trace(self, typeid): type_info = self.get(typeid) type_info.infobits |= (T_HAS_CUSTOM_TRACE | T_HAS_GCPTR)
return space.w_False if arr1.len == arr2.len: if comp_op == LT or comp_op == GT: return space.w_False return space.w_True if comp_op == LT or comp_op == LE: if arr1.len < arr2.len: return space.w_True return space.w_False if arr1.len > arr2.len: return space.w_True return space.w_False UNICODE_ARRAY = lltype.Ptr( lltype.Array(lltype.UniChar, hints={'nolength': True})) class W_ArrayBase(W_Root): _attrs_ = ('space', 'len', 'allocated', '_lifeline_', '_buffer') def __init__(self, space): self.space = space self.len = 0 self.allocated = 0 self._buffer = lltype.nullptr(rffi.CCHARP.TO) @rgc.must_be_light_finalizer def __del__(self): if self._buffer: lltype.free(self._buffer, flavor='raw')
uLong = rffi_platform.SimpleType('uLong', rffi.ULONG) Bytef = rffi_platform.SimpleType('Bytef', rffi.UCHAR) voidpf = rffi_platform.SimpleType('voidpf', rffi.VOIDP) ZLIB_VERSION = rffi_platform.DefinedConstantString('ZLIB_VERSION') for _name in constantnames: setattr(SimpleCConfig, _name, rffi_platform.ConstantInteger(_name)) config = rffi_platform.configure(SimpleCConfig) voidpf = config['voidpf'] uInt = config['uInt'] uLong = config['uLong'] Bytef = config['Bytef'] Bytefp = lltype.Ptr(lltype.Array(Bytef, hints={'nolength': True})) ZLIB_VERSION = config['ZLIB_VERSION'] for _name in constantnames: globals()[_name] = config[_name] # The following parameter is copied from zutil.h, version 0.95, # according to CPython's zlibmodule.c DEFLATED = Z_DEFLATED if MAX_MEM_LEVEL >= 8: DEF_MEM_LEVEL = 8 else: DEF_MEM_LEVEL = MAX_MEM_LEVEL OUTPUT_BUFFER_SIZE = 32 * 1024
from rpython.rtyper.lltypesystem import llmemory, lltype, rffi from rpython.rtyper.tool import rffi_platform as platform from rpython.rtyper.annlowlevel import llhelper from rpython.translator.tool.cbuild import ExternalCompilationInfo from Builtins import * from Core import * import Config, Target eci = ExternalCompilationInfo(includes=["libxml/parser.h"], \ include_dirs=Config.LIBXML2_INCLUDE_DIRS, \ library_dirs=Config.LIBXML2_LIBRARY_DIRS, \ libraries=Config.LIBXML2_LIBRARIES, \ link_extra=Config.LIBXML2_LINK_FLAGS, \ link_files=[Config.LIBXML2_A]) xmlCharP = lltype.Ptr(lltype.Array(rffi.UCHAR, hints={'nolength': True})) xmlCharPP = lltype.Ptr(lltype.Array(xmlCharP, hints={'nolength': True})) charactersSAXFunc = lltype.FuncType((rffi.VOIDP, xmlCharP, rffi.INT), lltype.Void) charactersSAXFuncP = lltype.Ptr(charactersSAXFunc) startElementNsSAX2Func = lltype.FuncType((rffi.VOIDP, xmlCharP, xmlCharP, xmlCharP, rffi.INT, \ xmlCharPP, rffi.INT, rffi.INT, xmlCharPP), lltype.Void) startElementNsSAX2FuncP = lltype.Ptr(startElementNsSAX2Func) endElementNsSAX2Func = lltype.FuncType( (rffi.VOIDP, xmlCharP, xmlCharP, xmlCharP), lltype.Void) endElementNsSAX2FuncP = lltype.Ptr(endElementNsSAX2Func) class CConfig: _compilation_info_ = eci xmlSAXHandler = platform.Struct("struct _xmlSAXHandler", \
eci = ExternalCompilationInfo( includes=[cwd.join('locale_codec.h')], include_dirs=[str(cwd), cdir], separate_module_files=[cwd.join('locale_codec.c')]) def llexternal(*args, **kwargs): kwargs.setdefault('compilation_info', eci) kwargs.setdefault('sandboxsafe', True) kwargs.setdefault('_nowrapper', True) return rffi.llexternal(*args, **kwargs) # An actual wchar_t*, rffi.CWCHARP is an array of UniChar (possibly on a # narrow build) RAW_WCHARP = lltype.Ptr(lltype.Array(rffi.WCHAR_T, hints={'nolength': True})) pypy_char2wchar = llexternal('pypy_char2wchar', [rffi.CCHARP, rffi.SIZE_TP], RAW_WCHARP) pypy_char2wchar_strict = llexternal('pypy_char2wchar_strict', [rffi.CCHARP, rffi.SIZE_TP], RAW_WCHARP) pypy_char2wchar_free = llexternal('pypy_char2wchar_free', [RAW_WCHARP], lltype.Void) pypy_wchar2char = llexternal('pypy_wchar2char', [RAW_WCHARP, rffi.SIZE_TP], rffi.CCHARP) pypy_wchar2char_strict = llexternal('pypy_wchar2char_strict', [RAW_WCHARP, rffi.SIZE_TP], rffi.CCHARP) pypy_wchar2char_free = llexternal('pypy_wchar2char_free', [rffi.CCHARP], lltype.Void) def utf8_encode_locale_strict(utf8, ulen):
as_pyobj) from pypy.module.cpyext.bytesobject import PyBytes_Check, PyBytes_FromObject from pypy.module._codecs.interp_codecs import (CodecState, latin_1_decode, utf_16_decode, utf_32_decode) from pypy.interpreter import unicodehelper from pypy.objspace.std import unicodeobject from rpython.rlib import rstring, runicode from rpython.tool.sourcetools import func_renamer import sys ## See comment in bytesobject.py. cts.parse_header(parse_dir / 'cpyext_unicodeobject.h') PyUnicodeObject = cts.gettype('PyUnicodeObject*') Py_UNICODE = cts.gettype('Py_UNICODE') INT_realP = lltype.Ptr(lltype.Array(rffi.INT_real, hints={'nolength': True})) @bootstrap_function def init_unicodeobject(space): make_typedescr(space.w_unicode.layout.typedef, basestruct=PyUnicodeObject.TO, attach=unicode_attach, dealloc=unicode_dealloc, realize=unicode_realize) # Buffer for the default encoding (used by PyUnicode_GetDefaultEncoding) DEFAULT_ENCODING_SIZE = 100 default_encoding = lltype.malloc(rffi.CCHARP.TO, DEFAULT_ENCODING_SIZE,
cnt = 0 for i in range(arr.len): index_count_jd.jit_merge_point( tp_item=tp_item, count=count, arrclass=arrclass) w_item = arr.w_getitem(space, i) if space.eq_w(w_item, w_val): if count: cnt += 1 else: return i if count: return cnt return -1 UNICODE_ARRAY = lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True})) class W_ArrayBase(W_Root): _attrs_ = ('space', 'len', 'allocated', '_lifeline_', '_buffer') def __init__(self, space): self.space = space self.len = 0 self.allocated = 0 self._buffer = lltype.nullptr(rffi.CCHARP.TO) @rgc.must_be_light_finalizer def __del__(self): if self._buffer: lltype.free(self._buffer, flavor='raw')
# ____________________________________________________________ # Access to the 'environ' external variable prefix = '' if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( '_NSGetEnviron', [], CCHARPPP, compilation_info=ExternalCompilationInfo(includes=['crt_externs.h'])) def os_get_environ(): return _os_NSGetEnviron()[0] elif _WIN32: eci = ExternalCompilationInfo(includes=['stdlib.h']) CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, '_environ', eci) get__wenviron, _set__wenviron = rffi.CExternVariable(CWCHARPP, '_wenviron', eci, c_type='wchar_t **') prefix = '_' else: os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ # # Lower-level interface: dummy placeholders and external registations
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.LLGraphCPU(None) NODE = lltype.GcForwardReference() NODE.become( lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed), ('floatval', lltype.Float), ('charval', lltype.Char), ('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') chardescr = cpu.fielddescrof(NODE, 'charval') 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)) quasiptr = quasibox.value 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) elidablecalldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_CANNOT_RAISE)) elidable2calldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_OR_MEMORYERROR)) elidable3calldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE)) 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)) raw_malloc_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_CAN_RAISE, oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) raw_free_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_RAW_FREE)) chararray = lltype.GcArray(lltype.Char) chararraydescr = cpu.arraydescrof(chararray) u2array = lltype.GcArray(rffi.USHORT) u2arraydescr = cpu.arraydescrof(u2array) # 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") complexarraycopydescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [complexarraydescr], [], [], [complexarraydescr], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) rawarraydescr = cpu.arraydescrof( lltype.Array(lltype.Signed, hints={'nolength': True})) rawarraydescr_char = cpu.arraydescrof( lltype.Array(lltype.Char, hints={'nolength': True})) rawarraydescr_float = cpu.arraydescrof( lltype.Array(lltype.Float, hints={'nolength': True})) fc_array = lltype.GcArray( lltype.Struct("floatchar", ("float", lltype.Float), ("char", lltype.Char))) fc_array_descr = cpu.arraydescrof(fc_array) fc_array_floatdescr = cpu.interiorfielddescrof(fc_array, "float") fc_array_chardescr = cpu.interiorfielddescrof(fc_array, "char") 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'), ]: if _name in ('strconcatdescr', 'strslicedescr'): _extra = EffectInfo.EF_ELIDABLE_OR_MEMORYERROR else: _extra = EffectInfo.EF_ELIDABLE_CANNOT_RAISE _oopspecindex = getattr(EffectInfo, _os) locals()[_name] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], _extra, oopspecindex=_oopspecindex)) # _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI')) locals()[_name.replace('str', 'unicode')] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], _extra, oopspecindex=_oopspecindex)) s2u_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE, oopspecindex=EffectInfo.OS_STR2UNICODE)) # class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though from rpython.jit.metainterp.virtualref import VirtualRefInfo class FakeWarmRunnerDesc: pass FakeWarmRunnerDesc.cpu = cpu vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc) virtualtokendescr = vrefinfo.descr_virtual_token virtualforceddescr = vrefinfo.descr_forced FUNC = lltype.FuncType([], lltype.Void) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE, can_invalidate=False, oopspecindex=EffectInfo.OS_JIT_FORCE_VIRTUALIZABLE) clear_vable = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) 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()
@cpython_api([PyObject], rffi.SIZE_T, error=-1) def _PyLong_NumBits(space, w_long): return space.uint_w(space.call_method(w_long, "bit_length")) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def _PyLong_Sign(space, w_long): assert isinstance(w_long, W_LongObject) return w_long.num.sign CONST_UCHARP = lltype.Ptr( lltype.Array(rffi.UCHAR, hints={ 'nolength': True, 'render_as_const': True })) @cpython_api([CONST_UCHARP, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject) def _PyLong_FromByteArray(space, bytes, n, little_endian, signed): little_endian = rffi.cast(lltype.Signed, little_endian) signed = rffi.cast(lltype.Signed, signed) s = rffi.charpsize2str(rffi.cast(rffi.CCHARP, bytes), rffi.cast(lltype.Signed, n)) if little_endian: byteorder = 'little' else: byteorder = 'big' result = rbigint.frombytes(s, byteorder, signed != 0)
from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib.debug import ll_assert from rpython.memory.gcheader import GCHeaderBuilder from rpython.memory.support import DEFAULT_CHUNK_SIZE from rpython.memory.support import get_address_stack, get_address_deque from rpython.memory.support import AddressDict, null_address_dict from rpython.memory.gc.hook import GcHooks from rpython.rtyper.lltypesystem.llmemory import NULL, raw_malloc_usage from rpython.rtyper.annlowlevel import cast_adr_to_nongc_instance TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed), ('size', lltype.Signed), ('links', lltype.Array(lltype.Signed))) ARRAY_TYPEID_MAP = lltype.GcArray(lltype.Ptr(TYPEID_MAP)) class GCBase(object): _alloc_flavor_ = "raw" moving_gc = False needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True can_usually_pin_objects = False object_minimal_size = 0 gcflag_extra = 0 # or a dedicated GC flag that the GC initializes to 0 gcflag_dummy = 0 # dedicated GC flag set only on rmodel.ll_dummy_value _totalroots_rpy = 0 # for inspector.py def __init__(self, config,
return lltype.malloc(BYTEARRAY, size) _, _, copy_bytearray_contents = rstr._new_copy_contents_fun( BYTEARRAY, BYTEARRAY, lltype.Char, 'bytearray') _, _, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun( rstr.STR, BYTEARRAY, lltype.Char, 'bytearray_from_str') def _empty_bytearray(): return empty BYTEARRAY.become( lltype.GcStruct( 'rpy_bytearray', ('chars', lltype.Array(lltype.Char)), adtmeths={ 'malloc': lltype.staticAdtMethod(mallocbytearray), 'copy_contents': lltype.staticAdtMethod(copy_bytearray_contents), 'copy_contents_from_str': lltype.staticAdtMethod(copy_bytearray_contents_from_str), 'length': rstr.LLHelpers.ll_length, 'empty': lltype.staticAdtMethod(_empty_bytearray), })) empty = lltype.malloc(BYTEARRAY, 0, immortal=True)
# SIZE_OF_FFI_ARG bytes, even if they may be smaller. (Unlike ffi_call, # we don't have any special rule about results that are integers smaller # than SIZE_OF_FFI_ARG). CIF_DESCRIPTION = lltype.Struct( 'CIF_DESCRIPTION', ('cif', FFI_CIF), ('abi', lltype.Signed), # these 4 fields could also be read directly ('nargs', lltype.Signed), # from 'cif', but doing so adds a dependency ('rtype', FFI_TYPE_P), # on the exact fields available from ffi_cif. ('atypes', FFI_TYPE_PP), # ('exchange_size', lltype.Signed), ('exchange_result', lltype.Signed), ('exchange_args', lltype.Array(lltype.Signed, hints={ 'nolength': True, 'immutable': True })), hints={'immutable': True}) CIF_DESCRIPTION_P = lltype.Ptr(CIF_DESCRIPTION) def jit_ffi_prep_cif(cif_description): """Minimal wrapper around ffi_prep_cif(). Call this after cif_description is initialized, in order to fill the last field: 'cif'. """ res = clibffi.c_ffi_prep_cif(cif_description.cif, cif_description.abi, cif_description.nargs, cif_description.rtype, cif_description.atypes) return rffi.cast(lltype.Signed, res)
def jitframe_allocate(frame_info): frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth, zero=True) frame.jf_frame_info = frame_info return frame JITFRAME = lltype.GcStruct( 'JITFRAME', ('hdr', lltype.Signed), ('jf_frame_info', lltype.Ptr(jitframe.JITFRAMEINFO)), ('jf_descr', llmemory.GCREF), ('jf_force_descr', llmemory.GCREF), ('jf_extra_stack_depth', lltype.Signed), ('jf_guard_exc', llmemory.GCREF), ('jf_gcmap', lltype.Ptr(jitframe.GCMAP)), ('jf_gc_trace_state', lltype.Signed), ('jf_frame', lltype.Array(lltype.Signed)), adtmeths = { 'allocate': jitframe_allocate, }, ) JITFRAMEPTR = lltype.Ptr(JITFRAME) class GCDescrShadowstackDirect(GcLLDescr_framework): layoutbuilder = None class GCClass: JIT_WB_IF_FLAG = 0 def __init__(self): GcCache.__init__(self, False, None)
see as the list of roots (stack and prebuilt objects). """ # XXX VERY INCOMPLETE, low coverage import py from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.memory.gctypelayout import TypeLayoutBuilder, FIN_HANDLER_ARRAY from rpython.rlib.rarithmetic import LONG_BIT, is_valid_int from rpython.memory.gc import minimark, incminimark from rpython.memory.gctypelayout import zero_gc_pointers_inside, zero_gc_pointers from rpython.rlib.debug import debug_print import pdb 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,
class LLtypeMixin(object): def get_class_of_box(self, box): base = box.getref_base() return lltype.cast_opaque_ptr(rclass.OBJECTPTR, base).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) node_vtable3 = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable3.name = rclass.alloc_array_name('node3') node_vtable3.subclassrange_min = 3 node_vtable3.subclassrange_max = 3 node_vtable_adr3 = llmemory.cast_ptr_to_adr(node_vtable3) cpu = runner.LLGraphCPU(None) NODE = lltype.GcForwardReference() S = lltype.GcForwardReference() NODE.become( lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed), ('floatval', lltype.Float), ('charval', lltype.Char), ('nexttuple', lltype.Ptr(S)), ('next', lltype.Ptr(NODE)))) S.become( lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('abis', lltype.Signed), ('b', lltype.Ptr(NODE)))) NODE2 = lltype.GcStruct('NODE2', ('parent', NODE), ('other', lltype.Ptr(NODE))) NODE3 = lltype.GcForwardReference() NODE3.become( lltype.GcStruct('NODE3', ('parent', OBJECT), ('value', lltype.Signed), ('next', lltype.Ptr(NODE3)), hints={'immutable': True})) big_fields = [('big' + i, lltype.Signed) for i in string.ascii_lowercase] BIG = lltype.GcForwardReference() BIG.become(lltype.GcStruct('BIG', *big_fields, hints={'immutable': True})) for field, _ in big_fields: locals()[field + 'descr'] = cpu.fielddescrof(BIG, field) node = lltype.malloc(NODE) node.value = 5 node.next = node node.parent.typeptr = node_vtable nodeaddr = lltype.cast_opaque_ptr(llmemory.GCREF, node) #nodebox = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, node)) node2 = lltype.malloc(NODE2) node2.parent.parent.typeptr = node_vtable2 node2addr = lltype.cast_opaque_ptr(llmemory.GCREF, node2) myptr = lltype.cast_opaque_ptr(llmemory.GCREF, node) mynodeb = lltype.malloc(NODE) myarray = lltype.cast_opaque_ptr( llmemory.GCREF, lltype.malloc(lltype.GcArray(lltype.Signed), 13, zero=True)) mynodeb.parent.typeptr = node_vtable myptrb = lltype.cast_opaque_ptr(llmemory.GCREF, mynodeb) myptr2 = lltype.malloc(NODE2) myptr2.parent.parent.typeptr = node_vtable2 myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, myptr2) nullptr = lltype.nullptr(llmemory.GCREF.TO) mynode3 = lltype.malloc(NODE3) mynode3.parent.typeptr = node_vtable3 mynode3.value = 7 mynode3.next = mynode3 myptr3 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode3) # a NODE2 mynode4 = lltype.malloc(NODE3) mynode4.parent.typeptr = node_vtable3 myptr4 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode4) # a NODE3 nullptr = lltype.nullptr(llmemory.GCREF.TO) #nodebox2 = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, node2)) nodesize = cpu.sizeof(NODE, node_vtable) node_tid = nodesize.get_type_id() nodesize2 = cpu.sizeof(NODE2, node_vtable2) nodesize3 = cpu.sizeof(NODE3, node_vtable3) valuedescr = cpu.fielddescrof(NODE, 'value') floatdescr = cpu.fielddescrof(NODE, 'floatval') chardescr = cpu.fielddescrof(NODE, 'charval') nextdescr = cpu.fielddescrof(NODE, 'next') nexttupledescr = cpu.fielddescrof(NODE, 'nexttuple') otherdescr = cpu.fielddescrof(NODE2, 'other') valuedescr3 = cpu.fielddescrof(NODE3, 'value') nextdescr3 = cpu.fielddescrof(NODE3, 'next') assert valuedescr3.is_always_pure() assert nextdescr3.is_always_pure() 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, None) quasi = lltype.malloc(QUASI, immortal=True) quasi.inst_field = -4247 quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field') quasiptr = lltype.cast_opaque_ptr(llmemory.GCREF, quasi) quasiimmutdescr = QuasiImmutDescr(cpu, quasiptr, 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') immut = lltype.malloc(INTOBJ_IMMUT, zero=True) immutaddr = lltype.cast_opaque_ptr(llmemory.GCREF, immut) noimmut_descr = cpu.sizeof(INTOBJ_NOIMMUT, intobj_noimmut_vtable) immut_descr = cpu.sizeof(INTOBJ_IMMUT, intobj_immut_vtable) PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT), ('ptrval', lltype.Ptr(OBJECT)), hints={'immutable': True}) ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) ptrobj_immut_descr = cpu.sizeof(PTROBJ_IMMUT, ptrobj_immut_vtable) immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval') arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed)) int32arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.INT)) int16arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.SHORT)) float32arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.SingleFloat)) arraydescr_tid = arraydescr.get_type_id() array = lltype.malloc(lltype.GcArray(lltype.Signed), 15, zero=True) arrayref = lltype.cast_opaque_ptr(llmemory.GCREF, array) array2 = lltype.malloc(lltype.GcArray(lltype.Ptr(S)), 15, zero=True) array2ref = lltype.cast_opaque_ptr(llmemory.GCREF, array2) gcarraydescr = cpu.arraydescrof(lltype.GcArray(llmemory.GCREF)) gcarraydescr_tid = gcarraydescr.get_type_id() floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float)) arrayimmutdescr = cpu.arraydescrof( lltype.GcArray(lltype.Signed, hints={"immutable": True})) immutarray = lltype.cast_opaque_ptr( llmemory.GCREF, lltype.malloc(arrayimmutdescr.A, 13, zero=True)) gcarrayimmutdescr = cpu.arraydescrof( lltype.GcArray(llmemory.GCREF, hints={"immutable": True})) floatarrayimmutdescr = cpu.arraydescrof( lltype.GcArray(lltype.Float, hints={"immutable": True})) # a GcStruct not inheriting from OBJECT tpl = lltype.malloc(S, zero=True) tupleaddr = lltype.cast_opaque_ptr(llmemory.GCREF, tpl) nodefull2 = lltype.malloc(NODE, zero=True) nodefull2addr = lltype.cast_opaque_ptr(llmemory.GCREF, nodefull2) ssize = cpu.sizeof(S, None) adescr = cpu.fielddescrof(S, 'a') abisdescr = cpu.fielddescrof(S, 'abis') 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))))) W_ROOT = lltype.GcStruct( 'W_ROOT', ('parent', OBJECT), ('inst_w_seq', llmemory.GCREF), ('inst_index', lltype.Signed), ('inst_w_list', llmemory.GCREF), ('inst_length', lltype.Signed), ('inst_start', lltype.Signed), ('inst_step', lltype.Signed)) inst_w_seq = cpu.fielddescrof(W_ROOT, 'inst_w_seq') inst_index = cpu.fielddescrof(W_ROOT, 'inst_index') inst_length = cpu.fielddescrof(W_ROOT, 'inst_length') inst_start = cpu.fielddescrof(W_ROOT, 'inst_start') inst_step = cpu.fielddescrof(W_ROOT, 'inst_step') inst_w_list = cpu.fielddescrof(W_ROOT, 'inst_w_list') w_root_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) tsize = cpu.sizeof(T, None) cdescr = cpu.fielddescrof(T, 'c') ddescr = cpu.fielddescrof(T, 'd') arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE3))) 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) SIMPLE = lltype.GcStruct('simple', ('parent', OBJECT), ('value', lltype.Signed)) simplevalue = cpu.fielddescrof(SIMPLE, 'value') simple_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) simpledescr = cpu.sizeof(SIMPLE, simple_vtable) simple = lltype.malloc(SIMPLE, zero=True) simpleaddr = lltype.cast_opaque_ptr(llmemory.GCREF, simple) #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) elidablecalldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_CANNOT_RAISE)) elidable2calldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_OR_MEMORYERROR)) elidable3calldescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([valuedescr], [], [], [valuedescr], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE)) 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], [])) writevalue3descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [valuedescr3], [], [])) 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)) raw_malloc_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_CAN_RAISE, oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) raw_free_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_RAW_FREE)) chararray = lltype.GcArray(lltype.Char) chararraydescr = cpu.arraydescrof(chararray) u2array = lltype.GcArray(rffi.USHORT) u2arraydescr = cpu.arraydescrof(u2array) nodefull = lltype.malloc(NODE2, zero=True) nodefull.parent.next = lltype.cast_pointer(lltype.Ptr(NODE), nodefull) nodefull.parent.nexttuple = tpl nodefulladdr = lltype.cast_opaque_ptr(llmemory.GCREF, nodefull) # 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") complexarraycopydescr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [complexarraydescr], [], [], [complexarraydescr], [], EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) rawarraydescr = cpu.arraydescrof( lltype.Array(lltype.Signed, hints={'nolength': True})) rawarraydescr_char = cpu.arraydescrof( lltype.Array(lltype.Char, hints={'nolength': True})) rawarraydescr_float = cpu.arraydescrof( lltype.Array(lltype.Float, hints={'nolength': True})) fc_array = lltype.GcArray( lltype.Struct("floatchar", ("float", lltype.Float), ("char", lltype.Char))) fc_array_descr = cpu.arraydescrof(fc_array) fc_array_floatdescr = cpu.interiorfielddescrof(fc_array, "float") fc_array_chardescr = cpu.interiorfielddescrof(fc_array, "char") 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'), ]: if _name in ('strconcatdescr', 'strslicedescr'): _extra = EffectInfo.EF_ELIDABLE_OR_MEMORYERROR else: _extra = EffectInfo.EF_ELIDABLE_CANNOT_RAISE _oopspecindex = getattr(EffectInfo, _os) locals()[_name] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], _extra, oopspecindex=_oopspecindex)) # _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI')) locals()[_name.replace('str', 'unicode')] = \ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], _extra, oopspecindex=_oopspecindex)) s2u_descr = cpu.calldescrof( FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE, oopspecindex=EffectInfo.OS_STR2UNICODE)) # class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though from rpython.jit.metainterp.virtualref import VirtualRefInfo class FakeWarmRunnerDesc: pass FakeWarmRunnerDesc.cpu = cpu vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc) virtualtokendescr = vrefinfo.descr_virtual_token virtualforceddescr = vrefinfo.descr_forced FUNC = lltype.FuncType([], lltype.Void) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE, can_invalidate=False, oopspecindex=EffectInfo.OS_JIT_FORCE_VIRTUALIZABLE) clear_vable = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) vref_descr = cpu.sizeof(vrefinfo.JIT_VIRTUAL_REF, jit_virtual_ref_vtable) FUNC = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CANNOT_RAISE, can_invalidate=False, oopspecindex=EffectInfo.OS_INT_PY_DIV) int_py_div_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CANNOT_RAISE, can_invalidate=False, oopspecindex=EffectInfo.OS_INT_UDIV) int_udiv_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CANNOT_RAISE, can_invalidate=False, oopspecindex=EffectInfo.OS_INT_PY_MOD) int_py_mod_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) FUNC = lltype.FuncType([], llmemory.GCREF) ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE) plain_r_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei) namespace = locals()
from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rtyper.lltypesystem.lltype import Ptr, FuncType, Void from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP, PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP, Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE) from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref from pypy.module.cpyext.modsupport import PyMethodDef P, FT, PyO = Ptr, FuncType, PyObject PyOPtr = Ptr(lltype.Array(PyO, hints={'nolength': True})) freefunc = P(FT([rffi.VOIDP], Void)) destructor = P(FT([PyO], Void)) printfunc = P(FT([PyO, FILEP, rffi.INT_real], rffi.INT)) getattrfunc = P(FT([PyO, rffi.CCHARP], PyO)) getattrofunc = P(FT([PyO, PyO], PyO)) setattrfunc = P(FT([PyO, rffi.CCHARP, PyO], rffi.INT_real)) setattrofunc = P(FT([PyO, PyO, PyO], rffi.INT_real)) cmpfunc = P(FT([PyO, PyO], rffi.INT_real)) reprfunc = P(FT([PyO], PyO)) hashfunc = P(FT([PyO], lltype.Signed)) richcmpfunc = P(FT([PyO, PyO, rffi.INT_real], PyO)) getiterfunc = P(FT([PyO], PyO)) iternextfunc = P(FT([PyO], PyO)) descrgetfunc = P(FT([PyO, PyO, PyO], PyO)) descrsetfunc = P(FT([PyO, PyO, PyO], rffi.INT_real)) initproc = P(FT([PyO, PyO, PyO], rffi.INT_real)) newfunc = P(FT([PyTypeObjectPtr, PyO, PyO], PyO)) allocfunc = P(FT([PyTypeObjectPtr, Py_ssize_t], PyO))
class GCData(object): """The GC information tables, and the query functions that the GC calls to decode their content. The encoding of this information is done by encode_type_shape(). These two places should be in sync, obviously, but in principle no other code should depend on the details of the encoding in TYPE_INFO. """ _alloc_flavor_ = 'raw' OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed) # A custom tracer (CT), enumerates the addresses that contain GCREFs. # It is called with the object as first argument, and the previous # returned address (or NULL the first time) as the second argument. FINALIZER_FUNC = lltype.FuncType([llmemory.Address], lltype.Void) FINALIZER = lltype.Ptr(FINALIZER_FUNC) # structure describing the layout of a typeid TYPE_INFO = lltype.Struct( "type_info", ("infobits", lltype.Signed), # combination of the T_xxx consts ("finalizer", FINALIZER), ("fixedsize", lltype.Signed), ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), hints={'immutable': True}, ) VARSIZE_TYPE_INFO = lltype.Struct( "varsize_type_info", ("header", TYPE_INFO), ("varitemsize", lltype.Signed), ("ofstovar", lltype.Signed), ("ofstolength", lltype.Signed), ("varofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), hints={'immutable': True}, ) TYPE_INFO_PTR = lltype.Ptr(TYPE_INFO) VARSIZE_TYPE_INFO_PTR = lltype.Ptr(VARSIZE_TYPE_INFO) def __init__(self, type_info_group): assert isinstance(type_info_group, llgroup.group) self.type_info_group = type_info_group self.type_info_group_ptr = type_info_group._as_ptr() def get(self, typeid): res = llop.get_group_member(GCData.TYPE_INFO_PTR, self.type_info_group_ptr, typeid) _check_valid_type_info(res) return res def get_varsize(self, typeid): res = llop.get_group_member(GCData.VARSIZE_TYPE_INFO_PTR, self.type_info_group_ptr, typeid) _check_valid_type_info_varsize(res) return res def q_is_varsize(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_IS_VARSIZE) != 0 def q_has_gcptr_in_varsize(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_HAS_GCPTR_IN_VARSIZE) != 0 def q_has_gcptr(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_HAS_GCPTR) != 0 def q_is_gcarrayofgcptr(self, typeid): infobits = self.get(typeid).infobits return (infobits & T_IS_GCARRAY_OF_GCPTR) != 0 def q_cannot_pin(self, typeid): typeinfo = self.get(typeid) ANY = (T_HAS_GCPTR | T_IS_WEAKREF) return (typeinfo.infobits & ANY) != 0 or bool(typeinfo.finalizer) def q_finalizer(self, typeid): return self.get(typeid).finalizer def q_light_finalizer(self, typeid): typeinfo = self.get(typeid) if typeinfo.infobits & T_HAS_LIGHTWEIGHT_FINALIZER: return typeinfo.finalizer return lltype.nullptr(GCData.FINALIZER_FUNC) def q_offsets_to_gc_pointers(self, typeid): return self.get(typeid).ofstoptrs def q_fixed_size(self, typeid): return self.get(typeid).fixedsize def q_varsize_item_sizes(self, typeid): return self.get_varsize(typeid).varitemsize def q_varsize_offset_to_variable_part(self, typeid): return self.get_varsize(typeid).ofstovar def q_varsize_offset_to_length(self, typeid): return self.get_varsize(typeid).ofstolength def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid): return self.get_varsize(typeid).varofstoptrs def q_weakpointer_offset(self, typeid): infobits = self.get(typeid).infobits if infobits & T_IS_WEAKREF: return weakptr_offset return -1 def q_member_index(self, typeid): infobits = self.get(typeid).infobits return infobits & T_MEMBER_INDEX def q_is_rpython_class(self, typeid): infobits = self.get(typeid).infobits return infobits & T_IS_RPYTHON_INSTANCE != 0 def q_has_custom_trace(self, typeid): infobits = self.get(typeid).infobits return infobits & T_HAS_CUSTOM_TRACE != 0 def q_fast_path_tracing(self, typeid): # return True if none of the flags T_HAS_GCPTR_IN_VARSIZE, # T_IS_GCARRAY_OF_GCPTR or T_HAS_CUSTOM_TRACE is set T_ANY_SLOW_FLAG = (T_HAS_GCPTR_IN_VARSIZE | T_IS_GCARRAY_OF_GCPTR | T_HAS_CUSTOM_TRACE) infobits = self.get(typeid).infobits return infobits & T_ANY_SLOW_FLAG == 0 def set_query_functions(self, gc): gc.set_query_functions( self.q_is_varsize, self.q_has_gcptr_in_varsize, self.q_is_gcarrayofgcptr, self.q_finalizer, self.q_light_finalizer, self.q_offsets_to_gc_pointers, self.q_fixed_size, self.q_varsize_item_sizes, self.q_varsize_offset_to_variable_part, self.q_varsize_offset_to_length, self.q_varsize_offsets_to_gcpointers_in_var_part, self.q_weakpointer_offset, self.q_member_index, self.q_is_rpython_class, self.q_has_custom_trace, self.q_fast_path_tracing, self.q_has_gcptr, self.q_cannot_pin) def _has_got_custom_trace(self, typeid): type_info = self.get(typeid) type_info.infobits |= (T_HAS_CUSTOM_TRACE | T_HAS_GCPTR)
assert gcref # not NULL! try: _gcflag_extras.remove(gcref) except KeyError: _gcflag_extras.add(gcref) toggle_gcflag_extra._subopnum = 3 def assert_no_more_gcflags(): if not we_are_translated(): assert not _gcflag_extras ARRAY_OF_CHAR = lltype.Array(lltype.Char) NULL_GCREF = lltype.nullptr(llmemory.GCREF.TO) class _GcRef(object): # implementation-specific: there should not be any after translation __slots__ = ['_x'] def __init__(self, x): self._x = x def __hash__(self): return object.__hash__(self._x) def __eq__(self, other): if isinstance(other, lltype._ptr):
c_ffi_call_return_type = rffi.INT else: c_ffi_call_return_type = lltype.Void c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP, VOIDPP], c_ffi_call_return_type, save_err=rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) # Note: the RFFI_ALT_ERRNO flag matches the one in pyjitpl.direct_libffi_call CALLBACK_TP = rffi.CCallback([FFI_CIFP, rffi.VOIDP, rffi.VOIDPP, rffi.VOIDP], lltype.Void) c_ffi_prep_closure = external( 'ffi_prep_closure', [FFI_CLOSUREP, FFI_CIFP, CALLBACK_TP, rffi.VOIDP], rffi.INT) FFI_STRUCT_P = lltype.Ptr( lltype.Struct('FFI_STRUCT', ('ffistruct', FFI_TYPE_P.TO), ('members', lltype.Array(FFI_TYPE_P)))) @specialize.arg(3) def make_struct_ffitype_e(size, aligment, field_types, track_allocation=True): """Compute the type of a structure. Returns a FFI_STRUCT_P out of which the 'ffistruct' member is a regular FFI_TYPE. """ tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types) + 1, flavor='raw', track_allocation=track_allocation) tpe.ffistruct.c_type = rffi.cast(rffi.USHORT, FFI_TYPE_STRUCT) tpe.ffistruct.c_size = rffi.cast(rffi.SIZE_T, size) tpe.ffistruct.c_alignment = rffi.cast(rffi.USHORT, aligment) tpe.ffistruct.c_elements = rffi.cast(FFI_TYPE_PP,