def add_jit_method(self, function_place: JITFunctionHoldPlace, argtypeids: call_record_t, argtypes: t.Tuple[type, ...]): method_arguments = function_place.method_arguments fn_ptr_name = function_place.fn_ptr_name actual_args = [cmc.typed_head + arg for arg in method_arguments] once_code_out = CodeOut() declaring: list = once_code_out[cmc.Import] typing: list = once_code_out[cmc.Customizable] typing.append("cdef {}({}):".format(fn_ptr_name, ', '.join(actual_args))) undef = object() for i, (actual_arg, arg, argtype) in enumerate( zip(actual_args, method_arguments, argtypes)): path = extension_type_pxd_paths.get(argtype, undef) if path is undef: # well, this type cannot JIT in fact, so still object and stop recording it. typing.append("{}{} = {}".format(cmc.IDENTATION_SECTION, arg, actual_arg)) elif path is None: # it's builtin extension types, like dict, list, etc. typing.append("{}cdef {} {} = {}".format(cmc.IDENTATION_SECTION, argtype.__name__, arg, actual_arg)) else: # Good, user-defined extension types! # You'll see how fast it'll be! # Firstly we import the required type typename = "{}{}".format(cmc.typed_head, i) declaring.append('from {} cimport {} as {}'.format( path, argtype.__name__, typename)) typing.append("{}cdef {} {} = {}".format(cmc.IDENTATION_SECTION, typename, arg, actual_arg)) once_code_out.merge_update(function_place.memoize_partial_code) code = '\n'.join(once_code_out.to_code_lines()) # TODO: use auto-evolution-able method lookup code = """ {} method_addr = reinterpret_cast[int64_t](<void*>{}) """.format(code, fn_ptr_name) unique_module = "Methods_{}_{}_JITed".format( id(function_place), function_place.name_that_makes_sense.replace('.', '__')) mod = compile_module(JIT_FUNCTION_DIR, unique_module, code) method_init_fptrs = getattr(mod, cmc.method_init_fptrs) method_init_globals = getattr(mod, cmc.method_init_globals) g = function_place.globals method_init_globals(**{k: g[k] for k in function_place.glob_deps}) method_init_fptrs(self.jit_fptr_index) function_place.methods[argtypeids] = mod.method_addr
def generate_base_method(self, function_place: JITFunctionHoldPlace, code): argc = function_place.argc method_argtype_comma_lst = ', '.join('object' for _ in range(argc)) method_get_argument_comma_lst = ', '.join('int64_t _%d' % i for i in range(argc)) # TODO: use auto-evolution-able method lookup fn_ptr_name = function_place.fn_ptr_name code = """ {} ctypedef object (*method_t)({}) cdef method_t this_method_getter({}): return {} base_method_addr = reinterpret_cast[int64_t](<void*>{}) method_getter_addr = reinterpret_cast[int64_t](<void*>this_method_getter) """.format(code, method_argtype_comma_lst, method_get_argument_comma_lst, fn_ptr_name, fn_ptr_name) if self.store_base_method_log: function_place.base_method_code = code unique_module = "Methods_{}_{}_base_method".format( id(function_place), function_place.name_that_makes_sense.replace('.', '__')) mod = compile_module(JIT_FUNCTION_DIR, unique_module, code) method_init_fptrs = getattr(mod, cmc.method_init_fptrs) method_init_globals = getattr(mod, cmc.method_init_globals) init_notifier = getattr(mod, cmc.method_init_recorder_and_notifier) method_getter_addr = getattr(mod, 'method_getter_addr') call_recorder = mod.NonJITCallRecorder() function_place.call_recorder = call_recorder init_notifier( call_recorder, lambda: self.jit_hotspot_analysis.trigger_jit(function_place)) g = function_place.globals method_init_globals(**{k: g[k] for k in function_place.glob_deps}) method_init_fptrs(self.jit_fptr_index) function_place.base_method_module = mod function_place.function_module.f.mut_method_get(method_getter_addr) function_place.base_method_addr = mod.base_method_addr
float object cdef class MyClass: pass cdef f(C x): cdef int a = pytoint(cython.typeof(x)) return a def g(C x): return f(x) def h(): z = cython.typeof(h) return check_ptr_eq(z, cython.typeof(object)) """ mod = compile_module('m', mod) print(mod.h()) a = mod.g(mod.MyClass()) assert isinstance(a, int) assert a == mod.g(mod.MyClass()) b = mod.g(1) assert isinstance(b, int) assert b == mod.g(1) assert a != b
cdef fused ty_f_Arg1: object cdef fused ty_f_Arg2: object cdef fused ty_f_Arg3: object cpdef ff(ty_f_Arg1 x, ty_f_Arg2 y, ty_f_Arg3 z): return x + y + z """ mod = compile_module("a", mod) print(mod.s(1, 2, 3)) def f(x, y, z): return x + y + z template = "f(1, 2, 3)" def test(f): t = timeit(template, number=10_000_000, globals=dict(f=f)) print(f, 'costs', t)
def _rebuild_method_getter_and_set(self): code = mk_hard_coded_method_getter_module(self.methods, self.base_method_addr, self.argc) mod = compile_module(JIT_FUNCTION_DIR, "MethodGetter", code) self.function_module.f.mut_method_get(mod.method_get_addr)
def generate_module_for_code(self, code_info: PyCodeInfo): code = mk_module_code(code_info) unique_module_name = "Functions_{}".format(self.fn_count) mod = compile_module(JIT_FUNCTION_DIR, unique_module_name, code) return mod