def generic_resolve(self, instance, attr): if attr in instance.struct: # It's a struct field => the type is well-known return instance.struct[attr] elif attr in instance.jitmethods: # It's a jitted method => typeinfer it meth = instance.jitmethods[attr] disp_type = types.Dispatcher(meth) class MethodTemplate(templates.AbstractTemplate): key = (self.key, attr) def generic(self, args, kws): args = (instance, ) + tuple(args) sig = disp_type.get_call_type(self.context, args, kws) return sig.as_method() return types.BoundFunction(MethodTemplate, instance) elif attr in instance.jitprops: # It's a jitted property => typeinfer its getter impdct = instance.jitprops[attr] getter = impdct['get'] disp_type = types.Dispatcher(getter) sig = disp_type.get_call_type(self.context, (instance, ), {}) return sig.return_type
def imp(context, builder, sig, args): instance_type = sig.args[0] method = instance_type.jitmethods[attr] disp_type = types.Dispatcher(method) call = context.get_function(types.Dispatcher(method), sig) out = call(builder, args) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out)
def __init__(self, py_func, locals={}, targetoptions={}, impl_kind='direct'): """ Parameters ---------- py_func: function object to be compiled locals: dict, optional Mapping of local variable names to Numba types. Used to override the types deduced by the type inference engine. targetoptions: dict, optional Target-specific config options. """ self.typingctx = self.targetdescr.typing_context self.targetctx = self.targetdescr.target_context pysig = utils.pysignature(py_func) arg_count = len(pysig.parameters) can_fallback = not targetoptions.get('nopython', False) _DispatcherBase.__init__(self, arg_count, py_func, pysig, can_fallback) functools.update_wrapper(self, py_func) self.targetoptions = targetoptions self.locals = locals self._cache = NullCache() compiler_class = self._impl_kinds[impl_kind] self._impl_kind = impl_kind self._compiler = compiler_class(py_func, self.targetdescr, targetoptions, locals) self._cache_hits = collections.Counter() self._cache_misses = collections.Counter() self._type = types.Dispatcher(self) self.typingctx.insert_global(self, self._type)
def typeof_global(self, inst, target, gvar): typ = self.context.resolve_value_type(gvar.value) if (typ is None and gvar.name == self.py_func.__name__ and gvar.name in _temporary_dispatcher_map): # Self-recursion case where the dispatcher is not (yet?) known # as a global variable typ = types.Dispatcher(_temporary_dispatcher_map[gvar.name]) if isinstance(typ, types.Dispatcher) and typ.dispatcher.is_compiling: # Recursive call if typ.dispatcher.py_func is self.py_func: typ = types.RecursiveCall(typ) else: raise NotImplementedError( "call to %s: mutual recursion not supported" % typ.dispatcher) if isinstance(typ, types.Array): # Global array in nopython mode is constant # XXX why layout='C'? typ = typ.copy(layout='C', readonly=True) if typ is not None: self.sentry_modified_builtin(inst, gvar) self.lock_type(target.name, typ, loc=inst.loc) self.assumed_immutables.add(inst) else: raise TypingError("Untyped global name '%s'" % gvar.name, loc=inst.loc)
def typeof_global(self, inst, target, gvar): try: typ = self.resolve_value_type(inst, gvar.value) except TypingError as e: if (gvar.name == self.func_id.func_name and gvar.name in _temporary_dispatcher_map): # Self-recursion case where the dispatcher is not (yet?) known # as a global variable typ = types.Dispatcher(_temporary_dispatcher_map[gvar.name]) else: e.patch_message("Untyped global name '%s': %s" % (gvar.name, e)) raise if isinstance(typ, types.Dispatcher) and typ.dispatcher.is_compiling: # Recursive call callframe = self.context.callstack.findfirst( typ.dispatcher.py_func) if callframe is not None: typ = types.RecursiveCall(typ) else: raise NotImplementedError("call to %s: unsupported recursion" % typ.dispatcher) if isinstance(typ, types.Array): # Global array in nopython mode is constant typ = typ.copy(readonly=True) self.sentry_modified_builtin(inst, gvar) self.lock_type(target.name, typ, loc=inst.loc) self.assumed_immutables.add(inst)
def attr_impl(context, builder, typ, value, attr): """ Generic getattr() for @jitclass instances. """ if attr in typ.struct: # It's a struct field inst = context.make_helper(builder, typ, value=value) data_pointer = inst.data data = context.make_data_helper(builder, typ.get_data_type(), ref=data_pointer) return imputils.impl_ret_borrowed(context, builder, typ.struct[attr], getattr(data, _mangle_attr(attr))) elif attr in typ.jitprops: # It's a jitted property getter = typ.jitprops[attr]['get'] sig = templates.signature(None, typ) dispatcher = types.Dispatcher(getter) sig = dispatcher.get_call_type(context.typing_context, [typ], {}) call = context.get_function(dispatcher, sig) out = call(builder, [value]) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out) raise NotImplementedError('attribute {0!r} not implemented'.format(attr))
def generic(self, args, kws): instance = args[0] if isinstance(instance, types.ClassInstanceType) and \ _dunder_meth in instance.jitmethods: meth = instance.jitmethods[_dunder_meth] disp_type = types.Dispatcher(meth) sig = disp_type.get_call_type(self.context, args, kws) return sig
def test_weaktype(self): d = Dummy() e = Dummy() a = types.Dispatcher(d) b = types.Dispatcher(d) c = types.Dispatcher(e) self.assertIs(a.dispatcher, d) self.assertIs(b.dispatcher, d) self.assertIs(c.dispatcher, e) # Equality of alive references self.assertTrue(a == b) self.assertFalse(a != b) self.assertTrue(a != c) self.assertFalse(a == c) z = types.int8 self.assertFalse(a == z) self.assertFalse(b == z) self.assertFalse(c == z) self.assertTrue(a != z) self.assertTrue(b != z) self.assertTrue(c != z) # Hashing and mappings s = set([a, b, c]) self.assertEqual(len(s), 2) self.assertIn(a, s) self.assertIn(b, s) self.assertIn(c, s) # Kill the references d = e = None gc.collect() with self.assertRaises(ReferenceError): a.dispatcher with self.assertRaises(ReferenceError): b.dispatcher with self.assertRaises(ReferenceError): c.dispatcher # Dead references are always unequal self.assertFalse(a == b) self.assertFalse(a == c) self.assertFalse(b == c) self.assertFalse(a == z) self.assertTrue(a != b) self.assertTrue(a != c) self.assertTrue(b != c) self.assertTrue(a != z)
def generic(self, args, kws): # Redirect resolution to __init__ instance_type = self.key.instance_type ctor = instance_type.jitmethods['__init__'] boundargs = (instance_type.get_reference_type(), ) + args disp_type = types.Dispatcher(ctor) sig = disp_type.get_call_type(self.context, boundargs, kws) # Actual constructor returns an instance value (not None) out = templates.signature(instance_type, *sig.args[1:]) return out
def ctor_impl(context, builder, sig, args): """ Generic constructor (__new__) for jitclasses. """ # Allocate the instance inst_typ = sig.return_type alloc_type = context.get_data_type(inst_typ.get_data_type()) alloc_size = context.get_abi_sizeof(alloc_type) meminfo = context.nrt.meminfo_alloc_dtor( builder, context.get_constant(types.uintp, alloc_size), imp_dtor(context, builder.module, inst_typ), ) data_pointer = context.nrt.meminfo_data(builder, meminfo) data_pointer = builder.bitcast(data_pointer, alloc_type.as_pointer()) # Nullify all data builder.store(cgutils.get_null_value(alloc_type), data_pointer) inst_struct = context.make_helper(builder, inst_typ) inst_struct.meminfo = meminfo inst_struct.data = data_pointer # Call the jitted __init__ # TODO: extract the following into a common util init_sig = (sig.return_type,) + sig.args init = inst_typ.jitmethods['__init__'] disp_type = types.Dispatcher(init) call = context.get_function(disp_type, types.void(*init_sig)) _add_linking_libs(context, call) realargs = [inst_struct._getvalue()] + list(args) call(builder, realargs) # Prepare return value ret = inst_struct._getvalue() return imputils.impl_ret_new_ref(context, builder, inst_typ, ret)
def attr_impl(context, builder, typ, value, attr): if attr in typ.struct: inst_struct = cgutils.create_struct_proxy(typ) inst = inst_struct(context, builder, value=value) data_pointer = inst.data data_struct = cgutils.create_struct_proxy(typ.get_data_type(), kind='data') data = data_struct(context, builder, ref=data_pointer) return imputils.impl_ret_borrowed(context, builder, typ.struct[attr], getattr(data, attr)) elif attr in typ.jitprops: getter = typ.jitprops[attr]['get'] sig = templates.signature(None, typ) dispatcher = types.Dispatcher(getter) sig = dispatcher.get_call_type(context.typing_context, [typ], {}) call = context.get_function(dispatcher, sig) out = call(builder, [value]) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out) raise NotImplementedError('attribute {0!r} not implemented'.format(attr))
def attr_impl(context, builder, sig, args, attr): """ Generic setattr() for @jitclass instances. """ typ, valty = sig.args target, val = args if attr in typ.struct: # It's a struct member instance_struct = cgutils.create_struct_proxy(typ) inst = instance_struct(context, builder, value=target) data_ptr = inst.data data_struct = cgutils.create_struct_proxy(typ.get_data_type(), kind='data') data = data_struct(context, builder, ref=data_ptr) # Get old value attr_type = typ.struct[attr] oldvalue = getattr(data, attr) # Store n setattr(data, attr, val) context.nrt_incref(builder, attr_type, val) # Delete old value context.nrt_decref(builder, attr_type, oldvalue) elif attr in typ.jitprops: # It's a jitted property setter = typ.jitprops[attr]['set'] disp_type = types.Dispatcher(setter) sig = disp_type.get_call_type(context.typing_context, (typ, valty), {}) call = context.get_function(disp_type, sig) call(builder, (target, val)) else: raise NotImplementedError( 'attribute {0!r} not implemented'.format(attr))
def set_attr_impl(context, builder, sig, args, attr): """ Generic setattr() for @jitclass instances. """ typ, valty = sig.args target, val = args if attr in typ.struct: # It's a struct member inst = context.make_helper(builder, typ, value=target) data_ptr = inst.data data = context.make_data_helper(builder, typ.get_data_type(), ref=data_ptr) # Get old value attr_type = typ.struct[attr] oldvalue = getattr(data, _mangle_attr(attr)) # Store n setattr(data, _mangle_attr(attr), val) context.nrt.incref(builder, attr_type, val) # Delete old value context.nrt.decref(builder, attr_type, oldvalue) elif attr in typ.jitprops: # It's a jitted property setter = typ.jitprops[attr]['set'] disp_type = types.Dispatcher(setter) sig = disp_type.get_call_type(context.typing_context, (typ, valty), {}) call = context.get_function(disp_type, sig) call(builder, (target, val)) _add_linking_libs(context, call) else: raise NotImplementedError( 'attribute {0!r} not implemented'.format(attr))
def _numba_type_(self): return types.Dispatcher(self)
def insert_overloaded(self, overloaded): self._insert_global(overloaded, types.Dispatcher(overloaded))
def insert_overloaded(self, overloaded): self.globals[overloaded] = types.Dispatcher(overloaded)
def imp(context, builder, sig, args): method = instance_type.jitmethods[attr] call = self.targetctx.get_function(types.Dispatcher(method), sig) out = call(builder, args) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out)