def specializectx(func): """A decorator that specializes 'func(ctx,...)' for each concrete subclass of AbstractMatchContext. During annotation, if 'ctx' is known to be a specific subclass, calling 'func' is a direct call; if 'ctx' is only known to be of class AbstractMatchContext, calling 'func' is an indirect call. """ assert func.func_code.co_varnames[0] == 'ctx' specname = '_spec_' + func.func_name while specname in _seen_specname: specname += '_' _seen_specname[specname] = True # Install a copy of the function under the name '_spec_funcname' in each # concrete subclass specialized_methods = [] for prefix, concreteclass in [('str', StrMatchContext), ('uni', UnicodeMatchContext)]: newfunc = func_with_new_name(func, prefix + specname) assert not hasattr(concreteclass, specname) setattr(concreteclass, specname, newfunc) specialized_methods.append(newfunc) # Return a dispatcher function, specialized on the exact type of 'ctx' def dispatch(ctx, *args): return getattr(ctx, specname)(*args) dispatch._annspecialcase_ = 'specialize:argtype(0)' dispatch._specialized_methods_ = specialized_methods return func_with_new_name(dispatch, specname)
def register_stat_variant(name): if sys.platform.startswith('win'): _functions = { 'stat': '_stati64', 'fstat': '_fstati64', 'lstat': '_stati64' } # no lstat on Windows c_func_name = _functions[name] elif sys.platform.startswith('linux'): # because we always use _FILE_OFFSET_BITS 64 - this helps things work that are not a c compiler _functions = {'stat': 'stat64', 'fstat': 'fstat64', 'lstat': 'lstat64'} c_func_name = _functions[name] else: c_func_name = name arg_is_path = (name != 'fstat') if arg_is_path: ARG1 = rffi.CCHARP else: ARG1 = rffi.INT os_mystat = rffi.llexternal(c_func_name, [ARG1, STAT_STRUCT], rffi.INT, compilation_info=compilation_info) def os_mystat_llimpl(arg): stresult = lltype.malloc(STAT_STRUCT.TO, flavor='raw') try: if arg_is_path: arg = rffi.str2charp(arg) error = rffi.cast(rffi.LONG, os_mystat(arg, stresult)) if arg_is_path: rffi.free_charp(arg) if error != 0: raise OSError(rposix.get_errno(), "os_?stat failed") return build_stat_result(stresult) finally: lltype.free(stresult, flavor='raw') def fakeimpl(arg): st = getattr(os, name)(arg) fields = [TYPE for fieldname, TYPE in LL_STAT_FIELDS] TP = TUPLE_TYPE(fields) ll_tup = lltype.malloc(TP.TO) for i, (fieldname, TYPE) in enumerate(LL_STAT_FIELDS): val = getattr(st, fieldname) rffi.setintfield(ll_tup, 'item%d' % i, int(val)) return ll_tup if arg_is_path: s_arg = str else: s_arg = int register_external(getattr(os, name), [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name, ), llimpl=func_with_new_name(os_mystat_llimpl, 'os_%s_llimpl' % (name, )), llfakeimpl=func_with_new_name(fakeimpl, 'os_%s_fake' % (name, )))
def register_stat_variant(name): if sys.platform.startswith('win'): _functions = {'stat': '_stati64', 'fstat': '_fstati64', 'lstat': '_stati64'} # no lstat on Windows c_func_name = _functions[name] elif sys.platform.startswith('linux'): # because we always use _FILE_OFFSET_BITS 64 - this helps things work that are not a c compiler _functions = {'stat': 'stat64', 'fstat': 'fstat64', 'lstat': 'lstat64'} c_func_name = _functions[name] else: c_func_name = name arg_is_path = (name != 'fstat') if arg_is_path: ARG1 = rffi.CCHARP else: ARG1 = rffi.INT os_mystat = rffi.llexternal(c_func_name, [ARG1, STAT_STRUCT], rffi.INT, compilation_info=compilation_info) def os_mystat_llimpl(arg): stresult = lltype.malloc(STAT_STRUCT.TO, flavor='raw') try: if arg_is_path: arg = rffi.str2charp(arg) error = rffi.cast(rffi.LONG, os_mystat(arg, stresult)) if arg_is_path: rffi.free_charp(arg) if error != 0: raise OSError(rposix.get_errno(), "os_?stat failed") return build_stat_result(stresult) finally: lltype.free(stresult, flavor='raw') def fakeimpl(arg): st = getattr(os, name)(arg) fields = [TYPE for fieldname, TYPE in LL_STAT_FIELDS] TP = TUPLE_TYPE(fields) ll_tup = lltype.malloc(TP.TO) for i, (fieldname, TYPE) in enumerate(LL_STAT_FIELDS): val = getattr(st, fieldname) rffi.setintfield(ll_tup, 'item%d' % i, int(val)) return ll_tup if arg_is_path: s_arg = str else: s_arg = int register_external(getattr(os, name), [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,), llimpl=func_with_new_name(os_mystat_llimpl, 'os_%s_llimpl' % (name,)), llfakeimpl=func_with_new_name(fakeimpl, 'os_%s_fake' % (name,)))
def test_func_rename_decorator(): def bar(): 'doc' bar2 = func_with_new_name(bar, 'bar2') assert bar.func_doc == bar2.func_doc == 'doc' bar.func_doc = 'new doc' bar3 = func_with_new_name(bar, 'bar3') assert bar3.func_doc == 'new doc' assert bar2.func_doc != bar3.func_doc
def _unaryop_impl(ufunc_name): def impl(self, space, w_out=None): from pypy.module.micronumpy import interp_ufuncs return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_out]) return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
def _binop_right_impl(ufunc_name): def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False): def impl(self, space, w_axis=None): if space.is_w(w_axis, space.w_None): w_axis = space.wrap(-1) return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space, self, True, promote_to_largest, w_axis) return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
def make_helper(firstarg, stmt, miniglobals): header = "def f(%s):" % (', '.join(argnames[firstarg:], )) source = py.code.Source(stmt) source = source.putaround(header) exec source.compile() in miniglobals f = miniglobals['f'] return func_with_new_name(f, 'memo_%s_%d' % (name, firstarg))
def _reduce_argmax_argmin_impl(op_name): reduce_driver = jit.JitDriver( greens=['shapelen', 'signature'], reds=['result', 'idx', 'i', 'self', 'cur_best', 'dtype'] ) def loop(self): i = self.start_iter() cur_best = self.eval(i) shapelen = len(self.shape) i = i.next(shapelen) dtype = self.find_dtype() result = 0 idx = 1 while not i.done(): reduce_driver.jit_merge_point(signature=self.signature, shapelen=shapelen, self=self, dtype=dtype, i=i, result=result, idx=idx, cur_best=cur_best) new_best = getattr(dtype, op_name)(cur_best, self.eval(i)) if dtype.ne(new_best, cur_best): result = idx cur_best = new_best i = i.next(shapelen) idx += 1 return result def impl(self, space): size = self.find_size() if size == 0: raise OperationError(space.w_ValueError, space.wrap("Can't call %s on zero-size arrays" \ % op_name)) return space.wrap(loop(self)) return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
def new_unary_math_function(name, can_overflow, c99): if sys.platform == 'win32' and c99: c_func = math_llexternal(name, [rffi.DOUBLE], rffi.DOUBLE) else: c_func = llexternal(name, [rffi.DOUBLE], rffi.DOUBLE) def ll_math(x): _error_reset() r = c_func(x) # Error checking fun. Copied from CPython 2.6 errno = rposix.get_errno() if isnan(r): if isnan(x): errno = 0 else: errno = EDOM elif isinf(r): if isinf(x) or isnan(x): errno = 0 elif can_overflow: errno = ERANGE else: errno = EDOM if errno: _likely_raise(errno, r) return r return func_with_new_name(ll_math, 'll_math_' + name)
def _new_copy_contents_fun(TP, CHAR_TP, name): def _str_ofs(item): return llmemory.offsetof(TP, "chars") + llmemory.itemoffsetof(TP.chars, 0) + llmemory.sizeof(CHAR_TP) * item @jit.oopspec("stroruni.copy_contents(src, dst, srcstart, dststart, length)") @enforceargs(None, None, int, int, int) def copy_string_contents(src, dst, srcstart, dststart, length): """Copies 'length' characters from the 'src' string to the 'dst' string, starting at position 'srcstart' and 'dststart'.""" # xxx Warning: don't try to do this at home. It relies on a lot # of details to be sure that it works correctly in all cases. # Notably: no GC operation at all from the first cast_ptr_to_adr() # because it might move the strings. The keepalive_until_here() # are obscurely essential to make sure that the strings stay alive # longer than the raw_memcopy(). assert srcstart >= 0 assert dststart >= 0 assert length >= 0 src = llmemory.cast_ptr_to_adr(src) + _str_ofs(srcstart) dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs(dststart) llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length) keepalive_until_here(src) keepalive_until_here(dst) copy_string_contents._always_inline_ = True return func_with_new_name(copy_string_contents, "copy_%s_contents" % name)
def add(Proto): for key, value in Proto.__dict__.items(): if (not key.startswith('__') and not key.startswith('_mixin_') or key == '__del__'): if hasattr(value, "func_name"): value = func_with_new_name(value, value.func_name) body[key] = value
def _binop_right_impl(ufunc_name): def impl(self, space, w_other): from pypy.module.micronumpy import interp_ufuncs return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
def _make_comparison_impl(symbol, specialnames): left, right = specialnames op = getattr(operator, left) def comparison_impl(space, w_obj1, w_obj2): #from pypy.objspace.std.tlistobject import W_TransparentList #if isinstance(w_obj1, W_TransparentList): # import pdb;pdb.set_trace() w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) w_first = w_obj1 w_second = w_obj2 if space.is_w(w_typ1, w_typ2): w_right_impl = None else: w_right_src, w_right_impl = space.lookup_in_type_where(w_typ2, right) if (w_left_src is not w_right_src # XXX see binop_impl and space.is_true(space.issubtype(w_typ2, w_typ1))): w_obj1, w_obj2 = w_obj2, w_obj1 w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: return w_res w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) if w_res is not None: return w_res # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... w_res = _cmp(space, w_first, w_second) res = space.int_w(w_res) return space.wrap(op(res, 0)) return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_'))
def _make_binop_impl(symbol, specialnames): left, right = specialnames def binop_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) if space.is_w(w_typ1, w_typ2): w_right_impl = None else: w_right_src, w_right_impl = space.lookup_in_type_where(w_typ2, right) # the logic to decide if the reverse operation should be tried # before the direct one is very obscure. For now, and for # sanity reasons, we just compare the two places where the # __xxx__ and __rxxx__ methods where found by identity. # Note that space.is_w() is potentially not happy if one of them # is None (e.g. with the thunk space)... if (w_left_src is not w_right_src # XXX and space.is_true(space.issubtype(w_typ2, w_typ1))): w_obj1, w_obj2 = w_obj2, w_obj1 w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: return w_res w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) if w_res is not None: return w_res raise OperationError(space.w_TypeError, space.wrap("unsupported operand type(s) for %s" % symbol)) return func_with_new_name(binop_impl, "binop_%s_impl"%left.strip('_'))
def generic_new_descr(W_Type): def descr_new(space, w_subtype, __args__): self = space.allocate_instance(W_Type, w_subtype) W_Type.__init__(self, space) return space.wrap(self) descr_new = func_with_new_name(descr_new, 'descr_new_%s' % W_Type.__name__) return interp2app(descr_new)
def _unaryop_impl(ufunc_name): def impl(self, space): from pypy.module.micronumpy import interp_ufuncs return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self]) return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
def _new_copy_contents_fun(TP, CHAR_TP, name): def _str_ofs(item): return (llmemory.offsetof(TP, 'chars') + llmemory.itemoffsetof(TP.chars, 0) + llmemory.sizeof(CHAR_TP) * item) @jit.oopspec('stroruni.copy_contents(src, dst, srcstart, dststart, length)' ) @enforceargs(None, None, int, int, int) def copy_string_contents(src, dst, srcstart, dststart, length): """Copies 'length' characters from the 'src' string to the 'dst' string, starting at position 'srcstart' and 'dststart'.""" # xxx Warning: don't try to do this at home. It relies on a lot # of details to be sure that it works correctly in all cases. # Notably: no GC operation at all from the first cast_ptr_to_adr() # because it might move the strings. The keepalive_until_here() # are obscurely essential to make sure that the strings stay alive # longer than the raw_memcopy(). assert srcstart >= 0 assert dststart >= 0 assert length >= 0 src = llmemory.cast_ptr_to_adr(src) + _str_ofs(srcstart) dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs(dststart) llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length) keepalive_until_here(src) keepalive_until_here(dst) copy_string_contents._always_inline_ = True return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name)
def setup(): for name in (ObjSpace.ConstantTable + ObjSpace.ExceptionTable + [ 'int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', 'basestring', 'object' ]): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # for (name, _, arity, _) in ObjSpace.MethodTable: if name == 'type': continue args = ['w_%d' % i for i in range(arity)] params = args[:] d = {'is_root': is_root, 'w_some_obj': w_some_obj} if name in ('get', ): params[-1] += '=None' exec compile2("""\ def meth(self, %s): %s return w_some_obj() """ % (', '.join(params), '; '.join( ['is_root(%s)' % arg for arg in args]))) in d meth = func_with_new_name(d['meth'], name) setattr(FakeObjSpace, name, meth) # for name in ObjSpace.IrregularOpTable: assert hasattr(FakeObjSpace, name) # missing?
def install_w_args_trampoline(type_, mm, is_local, op_name): def function(space, w_transparent_list, *args_w): args = Arguments(space, [space.wrap(op_name)] + list(args_w[:-1]), w_stararg=args_w[-1]) return space.call_args(w_transparent_list.w_controller, args) function = func_with_new_name(function, mm.name) mm.register(function, type_, *([W_ANY] * (mm.arity - 1)))
def _make_comparison_impl(symbol, specialnames): left, right = specialnames op = getattr(operator, left) def comparison_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) w_first = w_obj1 w_second = w_obj2 if _same_class_w(space, w_obj1, w_obj2, w_typ1, w_typ2): w_right_impl = None else: w_right_src, w_right_impl = space.lookup_in_type_where(w_typ2, right) # XXX see binop_impl if space.is_true(space.issubtype(w_typ2, w_typ1)): w_obj1, w_obj2 = w_obj2, w_obj1 w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: return w_res w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) if w_res is not None: return w_res # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... w_res = _cmp(space, w_first, w_second, symbol) res = space.int_w(w_res) return space.wrap(op(res, 0)) return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_'))
def make_helper(firstarg, stmt, miniglobals): header = "def f(%s):" % (', '.join(argnames[firstarg:],)) source = py.code.Source(stmt) source = source.putaround(header) exec source.compile() in miniglobals f = miniglobals['f'] return func_with_new_name(f, 'memo_%s_%d' % (name, firstarg))
def make_rsplit_with_delim(funcname, sliced): from pypy.tool.sourcetools import func_with_new_name def fn(space, w_self, w_by, w_maxsplit=-1): maxsplit = space.int_w(w_maxsplit) res_w = [] value = w_self._value end = len(value) by = w_by._value bylen = len(by) if bylen == 0: raise OperationError(space.w_ValueError, space.wrap("empty separator")) while maxsplit != 0: next = value.rfind(by, 0, end) if next < 0: break res_w.append(sliced(space, value, next+bylen, end, w_self)) end = next maxsplit -= 1 # NB. if it's already < 0, it stays < 0 res_w.append(sliced(space, value, 0, end, w_self)) res_w.reverse() return space.newlist(res_w) return func_with_new_name(fn, funcname)
def setup(): for name in (ObjSpace.ConstantTable + ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', 'basestring', 'object']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # for (name, _, arity, _) in ObjSpace.MethodTable: if name == 'type': continue args = ['w_%d' % i for i in range(arity)] params = args[:] d = {'is_root': is_root, 'w_some_obj': w_some_obj} if name in ('get',): params[-1] += '=None' exec compile2("""\ def meth(self, %s): %s return w_some_obj() """ % (', '.join(params), '; '.join(['is_root(%s)' % arg for arg in args]))) in d meth = func_with_new_name(d['meth'], name) setattr(FakeObjSpace, name, meth) # for name in ObjSpace.IrregularOpTable: assert hasattr(FakeObjSpace, name) # missing?
def _make_comparison_impl(symbol, specialnames): left, right = specialnames op = getattr(operator, left) def comparison_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) w_first = w_obj1 w_second = w_obj2 if space.is_w(w_typ1, w_typ2): w_right_impl = None else: w_right_src, w_right_impl = space.lookup_in_type_where( w_typ2, right) # XXX see binop_impl if space.is_true(space.issubtype(w_typ2, w_typ1)): w_obj1, w_obj2 = w_obj2, w_obj1 w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: return w_res w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) if w_res is not None: return w_res # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... w_res = _cmp(space, w_first, w_second) res = space.int_w(w_res) return space.wrap(op(res, 0)) return func_with_new_name(comparison_impl, 'comparison_%s_impl' % left.strip('_'))
def _reduce_argmax_argmin_impl(op_name): reduce_driver = jit.JitDriver(greens=['signature'], reds = ['i', 'size', 'result', 'self', 'cur_best', 'dtype']) def loop(self, size): result = 0 cur_best = self.eval(0) i = 1 dtype = self.find_dtype() while i < size: reduce_driver.jit_merge_point(signature=self.signature, self=self, dtype=dtype, size=size, i=i, result=result, cur_best=cur_best) new_best = getattr(dtype, op_name)(cur_best, self.eval(i)) if dtype.ne(new_best, cur_best): result = i cur_best = new_best i += 1 return result def impl(self, space): size = self.find_size() if size == 0: raise OperationError(space.w_ValueError, space.wrap("Can't call %s on zero-size arrays" \ % op_name)) return space.wrap(loop(self, size)) return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
def install_general_args_trampoline(type_, mm, is_local, op_name): def function(space, w_transparent_list, __args__): args = __args__.prepend(space.wrap(op_name)) return space.call_args(w_transparent_list.w_controller, args) function = func_with_new_name(function, mm.name) mm.register(function, type_)
def get_default_hash_function(cls): # go to the first parent class of 'cls' that has a typedef while 'typedef' not in cls.__dict__: cls = cls.__bases__[0] if cls is object: # not found: 'cls' must have been an abstract class, # no hash function is needed return None if cls.typedef.custom_hash: return None # the typedef says that instances have their own # hash, so we don't need a default RPython-level # hash function. try: hashfunction = _hashfunction_cache[cls] except KeyError: def hashfunction(w_obj): "Return the identity hash of 'w_obj'." assert isinstance(w_obj, cls) return hash(w_obj) # forces a hash_cache only on 'cls' instances hashfunction = func_with_new_name( hashfunction, 'hashfunction_for_%s' % (cls.__name__, )) _hashfunction_cache[cls] = hashfunction return hashfunction
def new_unary_math_function(name, can_overflow, c99): if sys.platform == 'win32' and c99: c_func = math_llexternal(name, [rffi.DOUBLE], rffi.DOUBLE) else: c_func = llexternal(name, [rffi.DOUBLE], rffi.DOUBLE) def ll_math(x): _error_reset() r = c_func(x) # Error checking fun. Copied from CPython 2.6 errno = rposix.get_errno() if not isfinite(r): if isnan(r): if isnan(x): errno = 0 else: errno = EDOM else: # isinf(r) if not isfinite(x): errno = 0 elif can_overflow: errno = ERANGE else: errno = EDOM if errno: _likely_raise(errno, r) return r return func_with_new_name(ll_math, 'll_math_' + name)
def specialize_call(self, hop): rtyper = hop.rtyper signature_args = self.normalize_args(*hop.args_s) args_r = [rtyper.getrepr(s_arg) for s_arg in signature_args] args_ll = [r_arg.lowleveltype for r_arg in args_r] s_result = hop.s_result r_result = rtyper.getrepr(s_result) ll_result = r_result.lowleveltype name = getattr(self, 'name', None) or self.instance.__name__ method_name = rtyper.type_system.name[:2] + 'typeimpl' fake_method_name = rtyper.type_system.name[:2] + 'typefakeimpl' impl = getattr(self, method_name, None) fakeimpl = getattr(self, fake_method_name, self.instance) if impl: if hasattr(self, fake_method_name): # If we have both an {ll,oo}impl and a {ll,oo}fakeimpl, # we need a wrapper that selects the proper one and calls it from pypy.tool.sourcetools import func_with_new_name # Using '*args' is delicate because this wrapper is also # created for init-time functions like llarena.arena_malloc # which are called before the GC is fully initialized args = ', '.join(['arg%d' % i for i in range(len(args_ll))]) d = {'original_impl': impl, 's_result': s_result, 'fakeimpl': fakeimpl, '__name__': __name__, } exec py.code.compile(""" from pypy.rlib.objectmodel import running_on_llinterp from pypy.rlib.debug import llinterpcall def ll_wrapper(%s): if running_on_llinterp: return llinterpcall(s_result, fakeimpl, %s) else: return original_impl(%s) """ % (args, args, args)) in d impl = func_with_new_name(d['ll_wrapper'], name + '_wrapper') if rtyper.annotator.translator.config.translation.sandbox: impl._dont_inline_ = True # 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(). impl._llfnobjattrs_ = { '_name': self.name, '_safe_not_sandboxed': self.safe_not_sandboxed, } obj = rtyper.getannmixlevel().delayedfunction( impl, signature_args, hop.s_result) else: #if not self.safe_not_sandboxed: # print '>>>>>>>>>>>>>-----------------------------------' # print name, self.name # print '<<<<<<<<<<<<<-----------------------------------' obj = rtyper.type_system.getexternalcallable(args_ll, ll_result, name, _external_name=self.name, _callable=fakeimpl, _safe_not_sandboxed=self.safe_not_sandboxed) vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r) hop.exception_is_here() return hop.genop('direct_call', vlist, r_result)
def new_dtype_getter(name): def get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) def new(space, w_subtype, w_value): dtype = get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(get_dtype)
class NonNativeUInt64(BaseType, NonNativeInteger): _attrs_ = () T = rffi.ULONGLONG BoxType = interp_boxes.W_UInt64Box format_code = "Q" _coerce = func_with_new_name(_uint64_coerce, '_coerce')
class Int64(BaseType, Integer): _attrs_ = () T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box format_code = "q" _coerce = func_with_new_name(_int64_coerce, '_coerce')
def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) def new(space, w_subtype, w_value): dtype = _get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(_get_dtype)
def _binop_right_impl(ufunc_name): def impl(self, space, w_other): w_other = scalar_w(space, interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()), w_other ) return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
def _make_unaryop_impl(symbol, specialnames): specialname, = specialnames def unaryop_impl(space, w_obj): w_impl = space.lookup(w_obj, specialname) if w_impl is None: raise OperationError(space.w_TypeError, space.wrap("operand does not support unary %s" % symbol)) return space.get_and_call_function(w_impl, w_obj) return func_with_new_name(unaryop_impl, 'unaryop_%s_impl'%specialname.strip('_'))
def _see_interp2app(self, interp2app): "NOT_RPYTHON" activation = interp2app._code.activation def check(): scope_w = [w_some_obj()] * NonConstant(42) w_result = activation._run(self, scope_w) is_root(w_result) check = func_with_new_name(check, 'check__' + interp2app.name) self._seen_extras.append(check)
def ufunc(func): signature = Signature() def impl(space, w_obj): if isinstance(w_obj, BaseArray): w_res = Call1(func, w_obj, w_obj.signature.transition(signature)) w_obj.invalidates.append(w_res) return w_res return space.wrap(func(space.float_w(w_obj))) return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
def new_malloc(TP, name): def mallocstr(length): ll_assert(length >= 0, "negative string length") r = malloc(TP, length) if not we_are_translated() or not malloc_zero_filled: r.hash = 0 return r mallocstr._annspecialcase_ = 'specialize:semierased' return func_with_new_name(mallocstr, name)
def build(cache, func): space = cache.space # make a built-in function assert isinstance(func.code, BuiltinCode) # XXX bltin = func.code._bltin unwrap_spec = func.code._unwrap_spec from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature( bltin.func_code) orig_sig = Signature(bltin, argnames, varargname, kwargname) tramp = UnwrapSpec_Trampoline(orig_sig) tramp.miniglobals = { '___space': space, '___W_Object': CPyObjSpace.W_Object, '___bltin': bltin, '___OperationError': OperationError, '___reraise': reraise, } tramp.apply_over(unwrap_spec) sourcelines = ['def trampoline(%s):' % (', '.join(tramp.inputargs),)] # this description is to aid viewing in graphviewer sourcelines.append(' "wrapper for fn: %s"' % func.name) for line in tramp.wrappings: sourcelines.append(' ' + line) sourcelines.append(' try:') sourcelines.append(' w_result = ___bltin(%s)' % ( ', '.join(tramp.passedargs),)) sourcelines.append(' except ___OperationError, e:') sourcelines.append(' ___reraise(e)') # the following line is not reached, unless we are translated # in which case it makes the function return (PyObject*)NULL. sourcelines.append(' w_result = ___W_Object()') sourcelines.append(' else:') # # convert None to Py_None sourcelines.append(' if w_result is None:') sourcelines.append(' return None') sourcelines.append(' return w_result.value') sourcelines.append('') miniglobals = tramp.miniglobals exec py.code.Source('\n'.join(sourcelines)).compile() in miniglobals trampoline = miniglobals['trampoline'] trampoline = func_with_new_name(trampoline, func.name) trampoline.nb_args = len(tramp.inputargs) trampoline.star_arg = tramp.star_arg trampoline.allow_someobjects = True # annotator hint trampoline._annspecialcase_ = "specialize:all_someobjects" if func.defs_w: trampoline.func_defaults = tuple([space.unwrap(w_x) for w_x in func.defs_w]) w_result = W_Object(trampoline) space.wrap_cache[id(w_result)] = w_result, func, follow_annotations return w_result
def _make_unaryop_impl(symbol, specialnames): specialname, = specialnames errormsg = "unsupported operand type for unary %s: '%%s'" % symbol def unaryop_impl(space, w_obj): w_impl = space.lookup(w_obj, specialname) if w_impl is None: typename = space.type(w_obj).getname(space) raise operationerrfmt(space.w_TypeError, errormsg, typename) return space.get_and_call_function(w_impl, w_obj) return func_with_new_name(unaryop_impl, 'unaryop_%s_impl'%specialname.strip('_'))
def build_type_checkers(type_name, cls=None): """ Builds two api functions: Py_XxxCheck() and Py_XxxCheckExact(). - if `cls` is None, the type is space.w_[type]. - if `cls` is a string, it is the name of a space attribute, e.g. 'w_str'. - else `cls` must be a W_Class with a typedef. """ if cls is None: attrname = "w_" + type_name.lower() def get_w_type(space): return getattr(space, attrname) elif isinstance(cls, str): def get_w_type(space): return getattr(space, cls) else: def get_w_type(space): return space.gettypeobject(cls.typedef) check_name = "Py" + type_name + "_Check" def check(space, w_obj): "Implements the Py_Xxx_Check function" w_obj_type = space.type(w_obj) w_type = get_w_type(space) return (space.is_w(w_obj_type, w_type) or space.is_true(space.issubtype(w_obj_type, w_type))) def check_exact(space, w_obj): "Implements the Py_Xxx_CheckExact function" w_obj_type = space.type(w_obj) w_type = get_w_type(space) return space.is_w(w_obj_type, w_type) check = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)(func_with_new_name( check, check_name)) check_exact = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)(func_with_new_name( check_exact, check_name + "Exact")) return check, check_exact
def define_call_function_retval(TYPE, typename): FUNCTYPE = lltype.Ptr(lltype.FuncType([], TYPE)) def call_function_retval_xyz(fnaddr, signature_index): fn = llmemory.cast_adr_to_ptr(fnaddr, FUNCTYPE) return fn() call_function_retval_xyz.stackless_explicit = True call_function_retval_xyz._dont_inline_ = True fnname = 'call_function_retval_' + typename fn = func_with_new_name(call_function_retval_xyz, fnname) globals()[fnname] = fn
def make_generic(funcname): def func(space, w_self): v = w_self._value if len(v) == 0: return space.w_False for idx in range(len(v)): if not getattr(unicodedb, funcname)(ord(v[idx])): return space.w_False return space.w_True return func_with_new_name(func, "unicode_%s__Unicode" % (funcname, ))
def unaryoperation(operationname): """NOT_RPYTHON""" def opimpl(f, *ignored): operation = getattr(f.space, operationname) w_1 = f.popvalue() w_result = operation(w_1) f.pushvalue(w_result) opimpl.unaryop = operationname return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname)
def _binop_right_impl(ufunc_name): def impl(self, space, w_other): w_other = scalar_w( space, interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()), w_other) return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)