def _setup_repr_final(self): self._setup_immutable_field_list() self._check_for_immutable_conflicts() if self.gcflavor == 'gc': if (self.classdef is not None and self.classdef.classdesc.lookup('__del__') is not None): s_func = self.classdef.classdesc.s_read_attribute('__del__') source_desc = self.classdef.classdesc.lookup('__del__') source_classdef = source_desc.getclassdef(None) source_repr = getinstancerepr(self.rtyper, source_classdef) assert len(s_func.descriptions) == 1 funcdesc, = s_func.descriptions graph = funcdesc.getuniquegraph() self.check_graph_of_del_does_not_call_too_much( self.rtyper, graph) FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None self.rtyper.call_all_setups() # compute ForwardReferences now args_s = [SomePtr(Ptr(OBJECT))] graph = self.rtyper.annotate_helper(ll_runtime_type_info, args_s) s = self.rtyper.annotation(graph.getreturnvar()) if (not isinstance(s, SomePtr) or s.ll_ptrtype != Ptr(RuntimeTypeInfo)): raise TyperError("runtime type info function returns %r, " "expected Ptr(RuntimeTypeInfo)" % (s)) funcptr = self.rtyper.getcallable(graph) attachRuntimeTypeInfo(self.object_type, funcptr, destrptr) vtable = self.rclass.getvtable() self.rtyper.set_type_for_typeptr(vtable, self.lowleveltype.TO)
def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) if self.gcflavor == 'gc': if (self.classdef is not None and self.classdef.classdesc.lookup('__del__') is not None): s_func = self.classdef.classdesc.s_read_attribute('__del__') source_desc = self.classdef.classdesc.lookup('__del__') source_classdef = source_desc.getclassdef(None) source_repr = getinstancerepr(self.rtyper, source_classdef) assert len(s_func.descriptions) == 1 funcdesc, = s_func.descriptions graph = funcdesc.getuniquegraph() self.check_graph_of_del_does_not_call_too_much(graph) FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None OBJECT = OBJECT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT, destrptr) vtable = self.rclass.getvtable() self.rtyper.set_type_for_typeptr(vtable, self.lowleveltype.TO)
def genexternalcall(self, fnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) f = functionptr(FUNCTYPE, fnname, **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf] + list(args_v), resulttype)
def OP_ADR_CALL(self, op): ARGTYPES = [v.concretetype for v in op.args[1:]] RESTYPE = op.result.concretetype FUNC = Ptr(FuncType(ARGTYPES, RESTYPE)) typename = self.db.gettype(FUNC) fnaddr = op.args[0] fnexpr = '((%s)%s)' % (cdecl(typename, ''), self.expr(fnaddr)) return self.generic_call(FUNC, fnexpr, op.args[1:], op.result)
def test_null_fnptr(): from rpython.flowspace.model import SpaceOperation, Constant from rpython.rtyper.lltypesystem.lltype import Void, FuncType, nullptr from rpython.translator.translator import TranslationContext t = TranslationContext() fnptr = nullptr(FuncType([], Void)) op = SpaceOperation('direct_call', [Constant(fnptr)], None) analyzer = BoolGraphAnalyzer(t) assert not analyzer.analyze(op)
def get_funcptr(self, rtyper, args_r, r_result): from rpython.rtyper.rtyper import llinterp_backend args_ll = [r_arg.lowleveltype for r_arg in args_r] ll_result = r_result.lowleveltype name = self.s_func.name if self.fakeimpl and rtyper.backend is llinterp_backend: FT = FuncType(args_ll, ll_result) return functionptr( FT, name, _external_name=name, _callable=self.fakeimpl) elif self.impl: if isinstance(self.impl, _ptr): return self.impl else: # store some attributes to the 'impl' function, where # the eventual call to rtyper.getcallable() will find them # and transfer them to the final lltype.functionptr(). self.impl._llfnobjattrs_ = {'_name': name} return rtyper.getannmixlevel().delayedfunction( self.impl, self.s_func.args_s, self.s_func.s_result) else: fakeimpl = self.fakeimpl or self.s_func.const FT = FuncType(args_ll, ll_result) return functionptr( FT, name, _external_name=name, _callable=fakeimpl)
hints={ 'immutable': True, 'shouldntbenull': True, 'typeptr': True }, rtti=True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become( Struct( 'object_vtable', #('parenttypeptr', CLASSTYPE), ('subclassrange_min', Signed), ('subclassrange_max', Signed), ('rtti', Ptr(RuntimeTypeInfo)), ('name', Ptr(rstr.STR)), ('instantiate', Ptr(FuncType([], OBJECTPTR))), hints={ 'immutable': True, 'static_immutable': True })) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} LLFLAVOR = {'gc': 'gc', 'raw': 'raw', 'stack': 'raw'} def cast_vtable_to_typeptr(vtable): while typeOf(vtable).TO != OBJECT_VTABLE: vtable = vtable.super
def expose_on_virtual_machine_proxy(unwrap_spec, result_type, minor=0, major=1): global MINOR, MAJOR mapping = {oop: sqInt, int: sqInt, list: sqIntArrayPtr, bool: sqInt, float: sqDouble, str: sqStr, long: sqLong, void: void} f_ptr = Ptr(FuncType([mapping[spec] for spec in unwrap_spec], mapping[result_type])) if MINOR < minor: MINOR = minor if MAJOR < major: MAJOR = major def decorator(func): len_unwrap_spec = len(unwrap_spec) assert len_unwrap_spec == len(inspect.getargspec(func)[0]), "wrong number of arguments" unrolling_unwrap_spec = unrolling_iterable(enumerate(unwrap_spec)) def wrapped(*c_arguments): assert len_unwrap_spec == len(c_arguments) args = () if IProxy.trace_proxy.is_set(): print 'Called InterpreterProxy >> %s' % func.func_name, assert IProxy.s_frame is not None and IProxy.space is not None and IProxy.interp is not None try: for i, spec in unrolling_unwrap_spec: c_arg = c_arguments[i] if spec is oop: args += (IProxy.oop_to_object(c_arg), ) elif spec is str: args += (rffi.charp2str(c_arg), ) else: args += (c_arg, ) result = func(*args) if IProxy.trace_proxy.is_set(): print '\t-> %s' % result if result_type is oop: assert isinstance(result, model.W_Object) return IProxy.object_to_oop(result) elif result_type in (int, float): assert isinstance(result, result_type) return result elif result_type is bool: assert isinstance(result, bool) if result: return 1 else: return 0 else: return result except error.PrimitiveFailedError: if IProxy.trace_proxy.is_set(): print '\t-> failed' IProxy.failed() from rpython.rlib.objectmodel import we_are_translated if not we_are_translated(): import pdb; pdb.set_trace() if mapping[result_type] is sqInt: return 0 elif mapping[result_type] is sqDouble: return 0.0 elif mapping[result_type] is sqIntArrayPtr: return rffi.cast(sqIntArrayPtr, 0) elif mapping[result_type] is sqLong: # XXX: how to return a long 0? return 0 elif mapping[result_type] is sqStr: return rffi.cast(sqStr, "") else: raise NotImplementedError( "InterpreterProxy: unknown result_type %s" % (result_type, )) wrapped.func_name = "wrapped_ipf_" + func.func_name functions.append((func.func_name, f_ptr, wrapped)) return wrapped return decorator
return getInterpreterProxy() # Redirect of sqGetInterpreterProxy, because the JIT doesn't allow calling of # functions annotated with @entrypoint. def getInterpreterProxy(): if not IProxy.vm_initialized: vm_proxy = lltype.malloc(VirtualMachine, flavor='raw') for func_name, signature, func in proxy_functions: setattr(vm_proxy, func_name, llhelper(signature, func)) IProxy.vm_proxy = vm_proxy IProxy.vm_initialized = True return IProxy.vm_proxy # rffi.llexternal is supposed to represent c-functions. func_str_void = Ptr(FuncType([], sqStr)) func_bool_vm = Ptr(FuncType([VMPtr], sqInt)) func_bool_void = Ptr(FuncType([], sqInt)) class _InterpreterProxy(object): _immutable_fields_ = ['vm_initialized?'] def __init__(self): self.vm_proxy = lltype.nullptr(VMPtr.TO) self.vm_initialized = False self.space = None self._next_oop = 0 self.oop_map = {} self.object_map = {} self.loaded_modules = {} self.remappable_objects = []