def get_external_function_sandbox_graph(fnobj, db, force_stub=False): """Build the graph of a helper trampoline function to be used in place of real calls to the external function 'fnobj'. The trampoline marshals its input arguments, dumps them to STDOUT, and waits for an answer on STDIN. """ fnname = fnobj._name if hasattr(fnobj, 'graph'): # get the annotation of the input arguments and the result graph = fnobj.graph annotator = db.translator.annotator args_s = [annotator.binding(v) for v in graph.getargs()] s_result = annotator.binding(graph.getreturnvar()) else: # pure external function - fall back to the annotations # corresponding to the ll types FUNCTYPE = lltype.typeOf(fnobj) args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNCTYPE.ARGS] s_result = annmodel.lltype_to_annotation(FUNCTYPE.RESULT) try: if force_stub: # old case - don't try to support suggested_primitive raise NotImplementedError("sandboxing for external function '%s'" % (fnname,)) dump_arguments = rmarshal.get_marshaller(tuple(args_s)) load_result = rmarshal.get_loader(s_result) except (NotImplementedError, rmarshal.CannotMarshal, rmarshal.CannotUnmarshall), e: msg = 'Not Implemented: %s' % (e,) log.WARNING(msg) def execute(*args): not_implemented_stub(msg)
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res, extra=None, extrakey=None): assert (extra is None) == (extrakey is None) key = (oopspec_name, tuple(ll_args), ll_res, extrakey) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra) if getattr(impl, 'need_result_type', False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # if hasattr(rtyper, 'annotator'): # regular case mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() else: # for testing only c_func = Constant(oopspec_name, lltype.Ptr(lltype.FuncType(ll_args, ll_res))) # if not hasattr(rtyper, '_builtin_func_for_spec_cache'): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): key = (oopspec_name, tuple(ll_args), ll_res) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s)) if getattr(impl, 'need_result_type', False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # if not hasattr(rtyper, '_builtin_func_for_spec_cache'): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def postprocess_timeshifting(self): annhelper = self.hrtyper.annhelper convert_result = getattr(self.main, 'convert_result', str) annotator = self.rtyper.annotator args_s = [annmodel.lltype_to_annotation(v.concretetype) for v in self.maingraph.getargs()] retvar = self.maingraph.getreturnvar() s_result = annmodel.lltype_to_annotation(retvar.concretetype) main_fnptr = self.rtyper.type_system.getcallable(self.maingraph) main = PseudoHighLevelCallable(main_fnptr, args_s, s_result) if hasattr(self.main, 'convert_arguments'): decoders = self.main.convert_arguments assert len(decoders) == len(args_s) else: decoders = [int] * len(args_s) decoders = unrolling_iterable(decoders) def ll_main(argv): args = () i = 1 for decoder in decoders: args += (decoder(argv[i]),) i = i + 1 try: res = main(*args) except Exception, e: os.write(1, 'EXCEPTION: %s\n' % (e,)) return 0 os.write(1, convert_result(res) + '\n') return 0
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): key = (oopspec_name, tuple(ll_args), ll_res) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if "." not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s)) if getattr(impl, "need_result_type", False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # if not hasattr(rtyper, "_builtin_func_for_spec_cache"): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def helper_func(self, FUNCPTR, func): if not self.cpu.translate_support_code: return llhelper(FUNCPTR, func) FUNC = get_functype(FUNCPTR) args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNC.ARGS] s_result = annmodel.lltype_to_annotation(FUNC.RESULT) graph = self.annhelper.getgraph(func, args_s, s_result) return self.annhelper.graph2delayed(graph, FUNC)
def compute_result_annotation(self, s_F, s_callable): assert s_F.is_constant() assert s_callable.is_constant() F = s_F.const args_s = [annmodel.lltype_to_annotation(T) for T in F.TO.ARGS] key = (llhelper, s_callable.const) s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s) assert annmodel.lltype_to_annotation(F.TO.RESULT).contains(s_res) return annmodel.SomePtr(F)
def _annotation(a, x): T = lltype.typeOf(x) if T == lltype.Ptr(ll_rstr.STR): t = str else: t = annmodel.lltype_to_annotation(T) return a.typeannotation(t)
def _compute_annotation(t, bookkeeper=None): from pypy.rpython.lltypesystem import lltype from pypy.rpython import extregistry if isinstance(t, SomeObject): return t elif isinstance(t, lltype.LowLevelType): return lltype_to_annotation(t) elif isinstance(t, list): assert len(t) == 1, "We do not support type joining in list" listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True) return SomeList(listdef) elif isinstance(t, tuple): return SomeTuple(tuple([annotation(i) for i in t])) elif isinstance(t, dict): assert len(t) == 1, "We do not support type joining in dict" result = SomeDict( DictDef(bookkeeper, annotation(t.keys()[0]), annotation(t.values()[0]))) return result elif type(t) is types.NoneType: return s_None elif extregistry.is_registered(t): entry = extregistry.lookup(t) entry.bookkeeper = bookkeeper return entry.compute_result_annotation() else: return annotationoftype(t, bookkeeper)
def simple_call(m, *args_s): _, meth = m.ootype._lookup(m.name) if isinstance(meth, ootype._overloaded_meth): return meth._resolver.annotate(args_s) else: METH = ootype.typeOf(meth) return lltype_to_annotation(METH.RESULT)
def compute_result_annotation(self, s_F, s_callable): assert s_F.is_constant() assert s_callable.is_constant() F = s_F.const if isinstance(F, ootype.OOType): FUNC = F resultcls = annmodel.SomeOOStaticMeth else: FUNC = F.TO resultcls = annmodel.SomePtr args_s = [annmodel.lltype_to_annotation(T) for T in FUNC.ARGS] key = (llhelper, s_callable.const) s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s) assert annmodel.lltype_to_annotation(FUNC.RESULT).contains(s_res) return resultcls(F)
def _compute_annotation(t, bookkeeper=None): from pypy.rpython.lltypesystem import lltype from pypy.annotation.bookkeeper import getbookkeeper from pypy.rpython import extregistry if isinstance(t, SomeObject): return t elif isinstance(t, lltype.LowLevelType): return lltype_to_annotation(t) elif isinstance(t, list): assert len(t) == 1, "We do not support type joining in list" listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True) return SomeList(listdef) elif isinstance(t, tuple): return SomeTuple(tuple([annotation(i) for i in t])) elif isinstance(t, dict): assert len(t) == 1, "We do not support type joining in dict" result = SomeDict(DictDef(bookkeeper, annotation(t.keys()[0]), annotation(t.values()[0]))) return result elif type(t) is types.NoneType: return s_None elif extregistry.is_registered(t): entry = extregistry.lookup(t) entry.bookkeeper = bookkeeper return entry.compute_result_annotation() else: return annotationoftype(t, bookkeeper)
def gendirectcall(self, ll_function, *args_v): rtyper = self.rtyper args_s = [] newargs_v = [] for v in args_v: if v.concretetype is Void: s_value = rtyper.binding(v, default=annmodel.s_None) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") if not isinstance(s_value, annmodel.SomePBC): raise TyperError("non-PBC Void argument: %r", (s_value,)) args_s.append(s_value) else: args_s.append(annmodel.lltype_to_annotation(v.concretetype)) newargs_v.append(v) self.rtyper.call_all_setups() # compute ForwardReferences now # hack for bound methods if hasattr(ll_function, 'im_func'): bk = rtyper.annotator.bookkeeper args_s.insert(0, bk.immutablevalue(ll_function.im_self)) newargs_v.insert(0, inputconst(Void, ll_function.im_self)) ll_function = ll_function.im_func graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s, rtyper.lowlevel_ann_policy) self.record_extra_call(graph) # build the 'direct_call' operation f = self.rtyper.getcallable(graph) c = inputconst(typeOf(f), f) fobj = self.rtyper.type_system_deref(f) return self.genop('direct_call', [c]+newargs_v, resulttype = typeOf(fobj).RESULT)
def gendirectcall(self, ll_function, *args_v): rtyper = self.rtyper args_s = [] newargs_v = [] for v in args_v: if v.concretetype is Void: s_value = rtyper.binding(v, default=annmodel.s_None) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") if not isinstance(s_value, annmodel.SomePBC): raise TyperError("non-PBC Void argument: %r", (s_value, )) args_s.append(s_value) else: args_s.append(annmodel.lltype_to_annotation(v.concretetype)) newargs_v.append(v) self.rtyper.call_all_setups() # compute ForwardReferences now # hack for bound methods if hasattr(ll_function, 'im_func'): bk = rtyper.annotator.bookkeeper args_s.insert(0, bk.immutablevalue(ll_function.im_self)) newargs_v.insert(0, inputconst(Void, ll_function.im_self)) ll_function = ll_function.im_func graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s, rtyper.lowlevel_ann_policy) self.record_extra_call(graph) # build the 'direct_call' operation f = self.rtyper.getcallable(graph) c = inputconst(typeOf(f), f) fobj = self.rtyper.type_system_deref(f) return self.genop('direct_call', [c] + newargs_v, resulttype=typeOf(fobj).RESULT)
def annotation(x): T = typeOf(x) if T == Ptr(PyObject) and someobjects: return object elif T == Ptr(rstr.STR): return str else: return lltype_to_annotation(T)
def call(m, args): args_s, kwds_s = args.unpack() if kwds_s: raise Exception("keyword arguments to call to a low-level bound method") inst = m.ootype._example() _, meth = ootype.typeOf(inst)._lookup(m.name) METH = ootype.typeOf(meth) return lltype_to_annotation(METH.RESULT)
def test_ll_calling_ll(self): A = GcArray(Float) B = GcArray(Signed) def ll_make(T, n): x = malloc(T, n) return x def ll_get(T, x, i): return x[i] def llf(): a = ll_make(A, 3) b = ll_make(B, 2) a[0] = 1.0 b[1] = 3 y0 = ll_get(A, a, 1) y1 = ll_get(B, b, 1) # a2 = ll_make(A, 4) a2[0] = 2.0 return ll_get(A, a2, 1) s = self.annotate(llf, []) a = self.a assert s == annmodel.SomeFloat() seen = {} ngraphs = len(a.translator.graphs) vTs = [] for call in annotated_calls(a): if derived(call, "ll_"): func, T = [x.value for x in call.args[0:2]] if (func, T) in seen: continue seen[func, T] = True desc = a.bookkeeper.getdesc(func) g = desc.specialize([a.binding(x) for x in call.args[1:]]) args = g.getargs() rv = g.getreturnvar() if func is ll_get: vT, vp, vi = args assert a.binding(vT) == a.bookkeeper.immutablevalue(T) assert a.binding(vi).knowntype == int assert a.binding(vp).ll_ptrtype.TO == T assert a.binding(rv) == annmodel.lltype_to_annotation(T.OF) elif func is ll_make: vT, vn = args assert a.binding(vT) == a.bookkeeper.immutablevalue(T) assert a.binding(vn).knowntype == int assert a.binding(rv).ll_ptrtype.TO == T else: assert False, func vTs.append(vT) assert len(seen) == 4 return a, vTs # reused by a test in test_rtyper
def lltype_to_annotation(cls, TYPE): if isinstance(TYPE, NativeInstance): return SomeOOInstance(TYPE) elif TYPE is ootype.Char: return SomeChar() elif TYPE is ootype.String: return SomeString(can_be_None=True) else: return lltype_to_annotation(TYPE)
def lltype_to_annotation(cls, TYPE): if isinstance(TYPE, NativeInstance): return SomeOOInstance(TYPE) elif TYPE is ootype.Char: return SomeChar() elif TYPE is ootype.String: return SomeString() else: return lltype_to_annotation(TYPE)
def getprimitiverepr(self, lltype): try: return self.primitive_to_repr[lltype] except KeyError: pass if isinstance(lltype, Primitive): repr = self.primitive_to_repr[lltype] = self.getrepr(annmodel.lltype_to_annotation(lltype)) return repr raise TyperError('There is no primitive repr for %r'%(lltype,))
def call(m, args): args_s, kwds_s = args.unpack() if kwds_s: raise Exception( "keyword arguments to call to a low-level bound method") inst = m.ootype._example() _, meth = ootype.typeOf(inst)._lookup(m.name) METH = ootype.typeOf(meth) return lltype_to_annotation(METH.RESULT)
def rtype_simple_call(self, hop): hop2 = hop.copy() func = self.func s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() hop2.v_s_insertfirstarg( v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch()
def getprimitiverepr(self, lltype): try: return self.primitive_to_repr[lltype] except KeyError: pass if isinstance(lltype, Primitive): repr = self.primitive_to_repr[lltype] = self.getrepr( annmodel.lltype_to_annotation(lltype)) return repr raise TyperError('There is no primitive repr for %r' % (lltype, ))
def compute_result_annotation(self, s_RESTYPE, s_pythonfunction, *args_s): from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype assert s_RESTYPE.is_constant() assert s_pythonfunction.is_constant() s_result = s_RESTYPE.const if isinstance(s_result, lltype.LowLevelType): s_result = annmodel.lltype_to_annotation(s_result) assert isinstance(s_result, annmodel.SomeObject) return s_result
def rtype_simple_call(self, hop): hop2 = hop.copy() func = self.func s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() hop2.v_s_insertfirstarg(v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch()
def _compile(self, fn, args, ann=None): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._llvm_func else: self._llvm_func = compile_function(fn, ann) self._func = fn self._ann = ann return self._llvm_func
def _compile(self, fn, args, ann=None, backendopt=True): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._cli_func else: self._cli_func = compile_function(fn, ann, backendopt=backendopt) self._func = fn self._ann = ann return self._cli_func
def consider_call_site(self, call_op): binding = self.annotator.binding s_callable = binding(call_op.args[0]) args_s = [binding(arg) for arg in call_op.args[1:]] if isinstance(s_callable, SomeLLADTMeth): adtmeth = s_callable s_callable = self.immutablevalue(adtmeth.func) args_s = [lltype_to_annotation(adtmeth.ll_ptrtype)] + args_s if isinstance(s_callable, SomePBC): s_result = binding(call_op.result, s_ImpossibleValue) self.consider_call_site_for_pbc(s_callable, call_op.opname, args_s, s_result, call_op)
def convert_scalar_to_array(r_item, v_item, llops): # x -> array([x]) s_item = lltype_to_annotation(r_item.lowleveltype) s_array = aarray.build_annotation_from_scalar(s_item) r_array = llops.rtyper.getrepr(s_array) from pypy.rpython.rmodel import inputconst cARRAY = inputconst(Void, r_array.ARRAY.TO) cITEM = inputconst(Void, r_array.ITEM) v_casted = llops.genop("cast_primitive", [v_item], r_array.ITEM) v_array = llops.gendirectcall(ll_build_from_scalar, cARRAY, v_casted) return r_array, v_array
def annotate_helper(self, ll_helper, ll_args, ll_result, inline=False): assert not self.finished_helpers args_s = map(annmodel.lltype_to_annotation, ll_args) s_result = annmodel.lltype_to_annotation(ll_result) graph = self.mixlevelannotator.getgraph(ll_helper, args_s, s_result) # the produced graphs does not need to be fully transformed self.need_minimal_transform(graph) if inline: self.graphs_to_inline[graph] = True FUNCTYPE = lltype.FuncType(ll_args, ll_result) return self.mixlevelannotator.graph2delayed(graph, FUNCTYPE=FUNCTYPE)
def _get_rmarshall_support_(self): # for rlib.rmarshal # reduce and recreate stat_result objects from 10-tuples # (we ignore the extra values here for simplicity and portability) def stat_result_reduce(st): return (st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9]) def stat_result_recreate(tup): return make_stat_result(tup + extra_zeroes) s_reduced = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE) for name, TYPE in PORTABLE_STAT_FIELDS]) extra_zeroes = (0,) * (len(STAT_FIELDS) - len(PORTABLE_STAT_FIELDS)) return s_reduced, stat_result_reduce, stat_result_recreate
def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False, exctrans=False): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._cli_func else: self._cli_func = compile_function(fn, ann, backendopt=backendopt, auto_raise_exc=auto_raise_exc, exctrans=exctrans) self._func = fn self._ann = ann return self._cli_func
def _compile(self, fn, args, ann=None): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return JvmGeneratedSourceWrapper(self._jvm_src) else: self._func = fn self._ann = ann self._jvm_src = generate_source_for_function(fn, ann) if not getoption('noasm'): self._jvm_src.compile() return JvmGeneratedSourceWrapper(self._jvm_src)
def compile(self, fn, args, ann=None, backendopt=False): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return JvmGeneratedSourceWrapper(self._jvm_src) else: self._func = fn self._ann = ann olddefs = patch_os() self._jvm_src = generate_source_for_function(fn, ann, backendopt) unpatch_os(olddefs) if not getoption('noasm'): self._jvm_src.compile() return JvmGeneratedSourceWrapper(self._jvm_src)
def convert_list_to_array(r_list, v_list, llops): # [...] -> array([...]) from pypy.rpython.rmodel import inputconst ITEM = r_list.item_repr.lowleveltype s_item = lltype_to_annotation(ITEM) key = type(s_item), s_item.knowntype typecode = aarray.numpy_typedict.get(key, None) ndim = 1 s_array = SomeArray(typecode, ndim) r_array = llops.rtyper.getrepr(s_array) cARRAY = inputconst(Void, r_array.ARRAY.TO) v_array = llops.gendirectcall(ll_build_from_list, cARRAY, v_list) # XX does a copy :P #v_array = llops.gendirectcall(ll_build_alias_to_list, cARRAY, v_list) # nice idea... return r_array, v_array
def robjmodel_hlinvoke(s_repr, s_llcallable, *args_s): from pypy.rpython import rmodel assert s_repr.is_constant() and isinstance(s_repr.const, rmodel.Repr),"hlinvoke expects a constant repr as first argument" r_func, nimplicitarg = s_repr.const.get_r_implfunc() nbargs = len(args_s) + nimplicitarg s_sigs = r_func.get_s_signatures((nbargs, (), False, False)) if len(s_sigs) != 1: raise TyperError("cannot hlinvoke callable %r with not uniform" "annotations: %r" % (s_repr.const, s_sigs)) _, s_ret = s_sigs[0] rresult = r_func.rtyper.getrepr(s_ret) return lltype_to_annotation(rresult.lowleveltype)
def __init__(self, rtyper): self.rtyper = rtyper if rtyper.type_system.name == "lltypesystem": self.stat_fields = ll_os_stat.STAT_FIELDS else: self.stat_fields = ll_os_stat.PORTABLE_STAT_FIELDS self.stat_field_indexes = {} for i, (name, TYPE) in enumerate(self.stat_fields): self.stat_field_indexes[name] = i self.s_tuple = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE) for name, TYPE in self.stat_fields]) self.r_tuple = rtyper.getrepr(self.s_tuple) self.lowleveltype = self.r_tuple.lowleveltype
def __init__(self, rtyper): self.rtyper = rtyper if rtyper.type_system.name == "lltypesystem": self.stat_fields = ll_os_stat.STAT_FIELDS else: self.stat_fields = ll_os_stat.PORTABLE_STAT_FIELDS self.stat_field_indexes = {} for i, (name, TYPE) in enumerate(self.stat_fields): self.stat_field_indexes[name] = i self.s_tuple = annmodel.SomeTuple([ annmodel.lltype_to_annotation(TYPE) for name, TYPE in self.stat_fields ]) self.r_tuple = rtyper.getrepr(self.s_tuple) self.lowleveltype = self.r_tuple.lowleveltype
def __init__(self, hrtyper, TYPE): RGenOp = hrtyper.RGenOp StructTypeDesc.__init__(self, hrtyper, TYPE) ACCESS = self.TYPE.ACCESS redirected_fields = ACCESS.redirected_fields self.redirected_fielddescs = [] self.redirected = {} i = 0 for fielddesc in self.fielddescs: if fielddesc.fieldname in redirected_fields: self.redirected_fielddescs.append((fielddesc, i)) self.redirected[i] = None i += 1 self.base_desc = self.getfielddesc('vable_base') self.rti_desc = self.getfielddesc('vable_rti') self.access_desc = self.getfielddesc('vable_access') TOPPTR = self.access_desc.PTRTYPE self.s_structtype = annmodel.lltype_to_annotation(TOPPTR) annhelper = hrtyper.annhelper self.my_redirected_getsetters_untouched = {} self.my_redirected_getsetters_touched = {} self.my_redirected_names = my_redirected_names = [] j = -1 for fielddesc, _ in self.redirected_fielddescs: j += 1 if fielddesc.PTRTYPE != self.PTRTYPE: continue my_redirected_names.append(fielddesc.fieldname) self._define_getset_field_ptr(hrtyper, fielddesc, j) access_untouched = lltype.malloc(ACCESS, immortal=True) access_touched = lltype.malloc(ACCESS, immortal=True) self._fill_access('untouched', access_untouched) self._fill_access('touched', access_touched) self.gv_access = RGenOp.constPrebuiltGlobal(access_untouched) self.touch_update = rvirtualizable.define_touch_update( TOPPTR, self.redirected_fielddescs, access_touched) self._define_collect_residual_args() self._define_access_is_null(hrtyper)
def annotate_helper(self, ll_function, argtypes): """Annotate the given low-level helper function and return its graph """ args_s = [] for s in argtypes: # assume 's' is a low-level type, unless it is already an annotation if not isinstance(s, annmodel.SomeObject): s = annmodel.lltype_to_annotation(s) args_s.append(s) # hack for bound methods if hasattr(ll_function, 'im_func'): bk = self.annotator.bookkeeper args_s.insert(0, bk.immutablevalue(ll_function.im_self)) ll_function = ll_function.im_func helper_graph = annotate_lowlevel_helper( self.annotator, ll_function, args_s, policy=self.lowlevel_ann_policy) return helper_graph
def _define_getset_field_ptr(self, hrtyper, fielddesc, j): annhelper = hrtyper.annhelper s_lltype = annmodel.lltype_to_annotation(fielddesc.RESTYPE) untouched = self.my_redirected_getsetters_untouched touched = self.my_redirected_getsetters_touched mkptr = annhelper.delayedfunction fnpairs = rvirtualizable.define_getset_field_ptrs(fielddesc, j) name = fielddesc.fieldname for getsetters, (get_field, set_field) in zip((untouched, touched), fnpairs): get_field_ptr = mkptr(get_field, [self.s_structtype], s_lltype, needtype=True) set_field_ptr = mkptr(set_field, [self.s_structtype, s_lltype], annmodel.s_None, needtype=True) getsetters[name] = get_field_ptr, set_field_ptr
def null(I_OR_SM): assert I_OR_SM.is_constant() null = ootype.null(I_OR_SM.const) r = lltype_to_annotation(ootype.typeOf(null)) return r