Skip to content

Commit e982764

Browse files
authored
Remove references to numba.experimental features (mutable structref, jitclass, first-class function types) (#459)
1 parent 9eb9e15 commit e982764

File tree

4 files changed

+2
-279
lines changed

4 files changed

+2
-279
lines changed

numba_cuda/numba/cuda/lowering.py

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,6 @@ def lower_call(self, resty, expr):
10271027
elif isinstance(fnty, types.RecursiveCall):
10281028
res = self._lower_call_RecursiveCall(fnty, expr, signature)
10291029

1030-
elif isinstance(fnty, types.FunctionType):
1031-
res = self._lower_call_FunctionType(fnty, expr, signature)
1032-
10331030
else:
10341031
res = self._lower_call_normal(fnty, expr, signature)
10351032

@@ -1227,136 +1224,6 @@ def _lower_call_RecursiveCall(self, fnty, expr, signature):
12271224
)
12281225
return res
12291226

1230-
def _lower_call_FunctionType(self, fnty, expr, signature):
1231-
self.debug_print("# calling first-class function type")
1232-
sig = types.unliteral(signature)
1233-
if not fnty.check_signature(signature):
1234-
# value dependent polymorphism?
1235-
raise UnsupportedError(
1236-
f"mismatch of function types:"
1237-
f" expected {fnty} but got {types.FunctionType(sig)}"
1238-
)
1239-
argvals = self.fold_call_args(
1240-
fnty,
1241-
sig,
1242-
expr.args,
1243-
expr.vararg,
1244-
expr.kws,
1245-
)
1246-
return self.__call_first_class_function_pointer(
1247-
fnty.ftype,
1248-
expr.func.name,
1249-
sig,
1250-
argvals,
1251-
)
1252-
1253-
def __call_first_class_function_pointer(self, ftype, fname, sig, argvals):
1254-
"""
1255-
Calls a first-class function pointer.
1256-
1257-
This function is responsible for calling a first-class function pointer,
1258-
which can either be a JIT-compiled function or a Python function. It
1259-
determines if a JIT address is available, and if so, calls the function
1260-
using the JIT address. Otherwise, it calls the function using a function
1261-
pointer obtained from the `__get_first_class_function_pointer` method.
1262-
1263-
Args:
1264-
ftype: The type of the function.
1265-
fname: The name of the function.
1266-
sig: The signature of the function.
1267-
argvals: The argument values to pass to the function.
1268-
1269-
Returns:
1270-
The result of calling the function.
1271-
"""
1272-
context = self.context
1273-
builder = self.builder
1274-
# Determine if jit address is available
1275-
fstruct = self.loadvar(fname)
1276-
struct = cgutils.create_struct_proxy(self.typeof(fname))(
1277-
context, builder, value=fstruct
1278-
)
1279-
jit_addr = struct.jit_addr
1280-
jit_addr.name = f"jit_addr_of_{fname}"
1281-
1282-
ctx = context
1283-
res_slot = cgutils.alloca_once(
1284-
builder, ctx.get_value_type(sig.return_type)
1285-
)
1286-
1287-
if_jit_addr_is_null = builder.if_else(
1288-
cgutils.is_null(builder, jit_addr), likely=False
1289-
)
1290-
with if_jit_addr_is_null as (then, orelse):
1291-
with then:
1292-
func_ptr = self.__get_first_class_function_pointer(
1293-
ftype, fname, sig
1294-
)
1295-
res = builder.call(func_ptr, argvals)
1296-
builder.store(res, res_slot)
1297-
1298-
with orelse:
1299-
llty = ctx.call_conv.get_function_type(
1300-
sig.return_type, sig.args
1301-
).as_pointer()
1302-
func_ptr = builder.bitcast(jit_addr, llty)
1303-
# call
1304-
status, res = ctx.call_conv.call_function(
1305-
builder, func_ptr, sig.return_type, sig.args, argvals
1306-
)
1307-
with cgutils.if_unlikely(builder, status.is_error):
1308-
context.call_conv.return_status_propagate(builder, status)
1309-
builder.store(res, res_slot)
1310-
return builder.load(res_slot)
1311-
1312-
def __get_first_class_function_pointer(self, ftype, fname, sig):
1313-
from numba.experimental.function_type import lower_get_wrapper_address
1314-
1315-
llty = self.context.get_value_type(ftype)
1316-
fstruct = self.loadvar(fname)
1317-
addr = self.builder.extract_value(
1318-
fstruct, 0, name="addr_of_%s" % (fname)
1319-
)
1320-
1321-
fptr = cgutils.alloca_once(
1322-
self.builder, llty, name="fptr_of_%s" % (fname)
1323-
)
1324-
with self.builder.if_else(
1325-
cgutils.is_null(self.builder, addr), likely=False
1326-
) as (then, orelse):
1327-
with then:
1328-
self.init_pyapi()
1329-
# Acquire the GIL
1330-
gil_state = self.pyapi.gil_ensure()
1331-
pyaddr = self.builder.extract_value(
1332-
fstruct, 1, name="pyaddr_of_%s" % (fname)
1333-
)
1334-
# try to recover the function address, see
1335-
# test_zero_address BadToGood example in
1336-
# test_function_type.py
1337-
addr1 = lower_get_wrapper_address(
1338-
self.context,
1339-
self.builder,
1340-
pyaddr,
1341-
sig,
1342-
failure_mode="ignore",
1343-
)
1344-
with self.builder.if_then(
1345-
cgutils.is_null(self.builder, addr1), likely=False
1346-
):
1347-
self.return_exception(
1348-
RuntimeError,
1349-
exc_args=(f"{ftype} function address is null",),
1350-
loc=self.loc,
1351-
)
1352-
addr2 = self.pyapi.long_as_voidptr(addr1)
1353-
self.builder.store(self.builder.bitcast(addr2, llty), fptr)
1354-
self.pyapi.decref(addr1)
1355-
self.pyapi.gil_release(gil_state)
1356-
with orelse:
1357-
self.builder.store(self.builder.bitcast(addr, llty), fptr)
1358-
return self.builder.load(fptr)
1359-
13601227
def _lower_call_normal(self, fnty, expr, signature):
13611228
# Normal function resolution
13621229
self.debug_print("# calling normal function: {0}".format(fnty))

numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
# SPDX-License-Identifier: BSD-2-Clause
33

44
from numba.cuda.testing import CUDATestCase
5-
import numba
6-
from numba.core.registry import cpu_target
75
from numba.cuda.core.compiler import CompilerBase
86
from numba.cuda.flags import Flags
97
from numba.cuda.core.compiler_machinery import PassManager
@@ -16,10 +14,8 @@
1614
FixupArgs,
1715
IRProcessing,
1816
)
19-
from numba.experimental import jitclass
2017
from numba.cuda.core.typed_passes import (
2118
NopythonTypeInference,
22-
type_inference_stage,
2319
DeadCodeElimination,
2420
)
2521
from numba.cuda.testing import skip_on_cudasim
@@ -29,41 +25,11 @@
2925
GLOBAL_B = 11
3026

3127

32-
@jitclass([("val", numba.core.types.List(numba.intp))])
33-
class Dummy(object):
34-
def __init__(self, val):
35-
self.val = val
36-
37-
3828
class TestIrUtils(CUDATestCase):
3929
"""
4030
Tests ir handling utility functions like find_callname.
4131
"""
4232

43-
@skip_on_cudasim("Skipping ir utils tests on CUDA simulator")
44-
def test_obj_func_match(self):
45-
"""Test matching of an object method (other than Array see #3449)"""
46-
47-
def test_func():
48-
d = Dummy([1])
49-
d.val.append(2)
50-
51-
test_ir = compiler.run_frontend(test_func)
52-
typingctx = cpu_target.typing_context
53-
targetctx = cpu_target.target_context
54-
typing_res = type_inference_stage(
55-
typingctx, targetctx, test_ir, (), None
56-
)
57-
matched_call = ir_utils.find_callname(
58-
test_ir, test_ir.blocks[0].body[7].value, typing_res.typemap
59-
)
60-
self.assertTrue(
61-
isinstance(matched_call, tuple)
62-
and len(matched_call) == 2
63-
and matched_call[0] == "append"
64-
)
65-
66-
@skip_on_cudasim("Skipping ir utils tests on CUDA simulator")
6733
def test_dead_code_elimination(self):
6834
class Tester(CompilerBase):
6935
@classmethod

numba_cuda/numba/cuda/tests/nocuda/test_import.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def test_no_impl_import(self):
4040
"numba.np.npyimpl",
4141
"numba.typed.typeddict",
4242
"numba.typed.typedlist",
43-
"numba.experimental.jitclass.base",
4443
)
4544

4645
code = "import sys; from numba import cuda; print(list(sys.modules))"

numba_cuda/numba/cuda/utils.py

Lines changed: 2 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
MACHINE_BITS, # noqa: F401
3333
DEVELOPER_MODE,
3434
) # noqa: F401
35-
from numba.core import types, config
35+
from numba.core import config
3636

37-
from collections.abc import Mapping, Sequence, MutableSet, MutableMapping
37+
from collections.abc import Mapping, MutableSet, MutableMapping
3838

3939
# Python version in (major, minor) tuple
4040
PYVERSION = sys.version_info[:2]
@@ -575,115 +575,6 @@ def get_nargs_range(pyfunc):
575575
return min_nargs, max_nargs
576576

577577

578-
def unify_function_types(numba_types):
579-
"""Return a normalized tuple of Numba function types so that
580-
581-
Tuple(numba_types)
582-
583-
becomes
584-
585-
UniTuple(dtype=<unified function type>, count=len(numba_types))
586-
587-
If the above transformation would be incorrect, return the
588-
original input as given. For instance, if the input tuple contains
589-
types that are not function or dispatcher type, the transformation
590-
is considered incorrect.
591-
"""
592-
dtype = unified_function_type(numba_types)
593-
if dtype is None:
594-
return numba_types
595-
return (dtype,) * len(numba_types)
596-
597-
598-
def unified_function_type(numba_types, require_precise=True):
599-
"""Returns a unified Numba function type if possible.
600-
601-
Parameters
602-
----------
603-
numba_types : Sequence of numba Type instances.
604-
require_precise : bool
605-
If True, the returned Numba function type must be precise.
606-
607-
Returns
608-
-------
609-
typ : {numba.core.types.Type, None}
610-
A unified Numba function type. Or ``None`` when the Numba types
611-
cannot be unified, e.g. when the ``numba_types`` contains at
612-
least two different Numba function type instances.
613-
614-
If ``numba_types`` contains a Numba dispatcher type, the unified
615-
Numba function type will be an imprecise ``UndefinedFunctionType``
616-
instance, or None when ``require_precise=True`` is specified.
617-
618-
Specifying ``require_precise=False`` enables unifying imprecise
619-
Numba dispatcher instances when used in tuples or if-then branches
620-
when the precise Numba function cannot be determined on the first
621-
occurrence that is not a call expression.
622-
"""
623-
from numba.core.errors import NumbaExperimentalFeatureWarning
624-
625-
if not (
626-
isinstance(numba_types, Sequence)
627-
and len(numba_types) > 0
628-
and isinstance(numba_types[0], (types.Dispatcher, types.FunctionType))
629-
):
630-
return
631-
632-
warnings.warn(
633-
"First-class function type feature is experimental",
634-
category=NumbaExperimentalFeatureWarning,
635-
)
636-
637-
mnargs, mxargs = None, None
638-
dispatchers = set()
639-
function = None
640-
undefined_function = None
641-
642-
for t in numba_types:
643-
if isinstance(t, types.Dispatcher):
644-
mnargs1, mxargs1 = get_nargs_range(t.dispatcher.py_func)
645-
if mnargs is None:
646-
mnargs, mxargs = mnargs1, mxargs1
647-
elif not (mnargs, mxargs) == (mnargs1, mxargs1):
648-
return
649-
dispatchers.add(t.dispatcher)
650-
t = t.dispatcher.get_function_type()
651-
if t is None:
652-
continue
653-
if isinstance(t, types.FunctionType):
654-
if mnargs is None:
655-
mnargs = mxargs = t.nargs
656-
elif not (mnargs == mxargs == t.nargs):
657-
return
658-
if isinstance(t, types.UndefinedFunctionType):
659-
if undefined_function is None:
660-
undefined_function = t
661-
else:
662-
# Refuse to unify using function type
663-
return
664-
dispatchers.update(t.dispatchers)
665-
else:
666-
if function is None:
667-
function = t
668-
else:
669-
assert function == t
670-
else:
671-
return
672-
if require_precise and (function is None or undefined_function is not None):
673-
return
674-
if function is not None:
675-
if undefined_function is not None:
676-
assert function.nargs == undefined_function.nargs
677-
function = undefined_function
678-
elif undefined_function is not None:
679-
undefined_function.dispatchers.update(dispatchers)
680-
function = undefined_function
681-
else:
682-
function = types.UndefinedFunctionType(mnargs, dispatchers)
683-
684-
return function
685-
686-
687578
class _RedirectSubpackage(ModuleType):
688579
"""Redirect a subpackage to a subpackage.
689580

0 commit comments

Comments
 (0)