Skip to content

Commit 662fd20

Browse files
committed
[GR-53366] Fixes for pyod
PullRequest: graalpython/3319
2 parents d1fb7f9 + 3d873ba commit 662fd20

File tree

6 files changed

+85
-7
lines changed

6 files changed

+85
-7
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_pystate.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@
3636
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
39+
import sys
3940

40-
from . import CPyExtTestCase, CPyExtFunction
41+
from . import CPyExtTestCase, CPyExtFunction, CPyExtType
4142

4243
__dir__ = __file__.rpartition("/")[0]
4344

4445

4546
class TestPystate(CPyExtTestCase):
46-
4747
test_PyThreadState_GetDict = CPyExtFunction(
4848
lambda args: type({}),
4949
lambda: (
@@ -58,3 +58,15 @@ class TestPystate(CPyExtTestCase):
5858
arguments=["PyObject* ignored"],
5959
callfunction="wrap_PyThreadState_GetDict",
6060
)
61+
62+
def test_PyThreadState_GetFrame(self):
63+
Tester = CPyExtType(
64+
"PyThreadState_GetFrameTester",
65+
code="""
66+
static PyObject* get_frame(PyObject* unused) {
67+
return (PyObject*)PyThreadState_GetFrame(PyThreadState_GET());
68+
}
69+
""",
70+
tp_methods='{"get_frame", (PyCFunction)get_frame, METH_NOARGS | METH_STATIC, NULL}',
71+
)
72+
assert Tester.get_frame() is sys._getframe(0)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextPyStateBuiltins.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored;
4545
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int;
4646
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Pointer;
47+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyFrameObjectTransfer;
4748
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectBorrowed;
4849
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyThreadState;
4950
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t;
@@ -55,18 +56,23 @@
5556
import com.oracle.graal.python.builtins.objects.PNone;
5657
import com.oracle.graal.python.builtins.objects.cext.capi.PThreadState;
5758
import com.oracle.graal.python.builtins.objects.dict.PDict;
59+
import com.oracle.graal.python.builtins.objects.frame.PFrame;
5860
import com.oracle.graal.python.builtins.objects.ints.PInt;
61+
import com.oracle.graal.python.nodes.frame.GetCurrentFrameRef;
62+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
5963
import com.oracle.graal.python.nodes.util.CannotCastException;
6064
import com.oracle.graal.python.runtime.GilNode;
6165
import com.oracle.graal.python.runtime.PythonContext;
6266
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
6367
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
6468
import com.oracle.graal.python.util.OverflowException;
6569
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
70+
import com.oracle.truffle.api.dsl.Bind;
6671
import com.oracle.truffle.api.dsl.Cached;
6772
import com.oracle.truffle.api.dsl.Specialization;
6873
import com.oracle.truffle.api.interop.InteropLibrary;
6974
import com.oracle.truffle.api.library.CachedLibrary;
75+
import com.oracle.truffle.api.nodes.Node;
7076

7177
public final class PythonCextPyStateBuiltins {
7278

@@ -131,6 +137,18 @@ PDict get(@Cached PythonObjectFactory factory) {
131137
}
132138
}
133139

140+
@CApiBuiltin(ret = PyFrameObjectTransfer, args = {PyThreadState}, call = Direct)
141+
abstract static class PyThreadState_GetFrame extends CApiUnaryBuiltinNode {
142+
@Specialization
143+
PFrame get(
144+
@Bind("this") Node inliningTarget,
145+
@Cached GetCurrentFrameRef getCurrentFrameRef,
146+
@Cached ReadCallerFrameNode readCallerFrameNode) {
147+
PFrame.Reference frameRef = getCurrentFrameRef.execute(null, inliningTarget);
148+
return readCallerFrameNode.executeWith(frameRef, 0);
149+
}
150+
}
151+
134152
@CApiBuiltin(ret = PyObjectBorrowed, args = {Py_ssize_t}, call = Ignored)
135153
abstract static class PyTruffleState_FindModule extends CApiUnaryBuiltinNode {
136154

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,6 @@ public final class CApiFunction {
865865
@CApiBuiltin(name = "PySys_WriteStdout", ret = Void, args = {ConstCharPtrAsTruffleString, VARARGS}, call = NotImplemented)
866866
@CApiBuiltin(name = "PyThreadState_Delete", ret = Void, args = {PyThreadState}, call = NotImplemented)
867867
@CApiBuiltin(name = "PyThreadState_EnterTracing", ret = Void, args = {PyThreadState}, call = NotImplemented)
868-
@CApiBuiltin(name = "PyThreadState_GetFrame", ret = PyFrameObjectTransfer, args = {PyThreadState}, call = NotImplemented)
869868
@CApiBuiltin(name = "PyThreadState_GetID", ret = UINT64_T, args = {PyThreadState}, call = NotImplemented)
870869
@CApiBuiltin(name = "PyThreadState_GetInterpreter", ret = PyInterpreterState, args = {PyThreadState}, call = NotImplemented)
871870
@CApiBuiltin(name = "PyThreadState_LeaveTracing", ret = Void, args = {PyThreadState}, call = NotImplemented)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/transitions/CApiTransitions.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,8 +1583,15 @@ Object doNonWrapper(long pointer, boolean stealing,
15831583
private static final int TP_REFCNT_OFFSET = 0;
15841584

15851585
private static long addNativeRefCount(long pointer, long refCntDelta) {
1586+
return addNativeRefCount(pointer, refCntDelta, false);
1587+
}
1588+
1589+
private static long addNativeRefCount(long pointer, long refCntDelta, boolean ignoreIfDead) {
15861590
assert PythonContext.get(null).isNativeAccessAllowed();
15871591
long refCount = UNSAFE.getLong(pointer + TP_REFCNT_OFFSET);
1592+
if (ignoreIfDead && refCount == 0) {
1593+
return 0;
1594+
}
15881595
assert (refCount & 0xFFFFFFFF00000000L) == 0 : String.format("suspicious refcnt value during managed adjustment for %016x (%d %016x + %d)\n", pointer, refCount, refCount, refCntDelta);
15891596
assert (refCount + refCntDelta) > 0 : String.format("refcnt reached zero during managed adjustment for %016x (%d %016x + %d)\n", pointer, refCount, refCount, refCntDelta);
15901597

@@ -1629,11 +1636,20 @@ private static Object createAbstractNativeObject(HandleContext handleContext, Ob
16291636

16301637
pollReferenceQueue();
16311638
PythonAbstractNativeObject result = new PythonAbstractNativeObject(obj);
1632-
NativeObjectReference ref = new NativeObjectReference(handleContext, result, pointer);
1633-
nativeLookupPut(getContext(), pointer, ref);
1634-
16351639
long refCntDelta = MANAGED_REFCNT - (transfer ? 1 : 0);
1636-
addNativeRefCount(pointer, refCntDelta);
1640+
/*
1641+
* Some APIs might be called from tp_dealloc/tp_del/tp_finalize where the refcount is 0. In
1642+
* that case we don't want to create a new reference, since that would resurrect the object
1643+
* and we would end up deallocating it twice.
1644+
*/
1645+
long refCount = addNativeRefCount(pointer, refCntDelta, true);
1646+
if (refCount > 0) {
1647+
NativeObjectReference ref = new NativeObjectReference(handleContext, result, pointer);
1648+
nativeLookupPut(getContext(), pointer, ref);
1649+
} else if (LOGGER.isLoggable(Level.FINE)) {
1650+
LOGGER.fine(PythonUtils.formatJString("createAbstractNativeObject: creating PythonAbstractNativeObject for a dying object (refcount 0): 0x%x", pointer));
1651+
}
1652+
16371653
return result;
16381654
}
16391655

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[[rules]]
2+
# Not upstreamable, we disable the JIT
3+
version = '== 0.59.1'
4+
patch = 'numba-0.59.1.patch'
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
diff --git a/numba/core/decorators.py b/numba/core/decorators.py
2+
index 21f1125..00a28fe 100644
3+
--- a/numba/core/decorators.py
4+
+++ b/numba/core/decorators.py
5+
@@ -217,6 +217,10 @@ def _jit(sigs, locals, target, cache, targetoptions, **dispatcher_args):
6+
f"{type(func)})."
7+
)
8+
9+
+ if sys.implementation.name == 'graalpy':
10+
+ if target == 'npyufunc':
11+
+ raise NotImplementedError("Cannot create npyufunc under graalpy")
12+
+ return func
13+
if config.ENABLE_CUDASIM and target == 'cuda':
14+
from numba import cuda
15+
return cuda.jit(func)
16+
diff --git a/pyproject.toml b/pyproject.toml
17+
new file mode 100644
18+
index 0000000..fecb79e
19+
--- /dev/null
20+
+++ b/pyproject.toml
21+
@@ -0,0 +1,8 @@
22+
+[build-system]
23+
+requires = ["setuptools >= 40.6.0", "wheel", "llvmlite<0.43,>=0.42.0dev0", "numpy<1.27,>=1.22", "versioneer"]
24+
+build-backend = "setuptools.build_meta"
25+
+
26+
+[tool.versioneer]
27+
+VCS = 'git'
28+
+versionfile_source = 'numba/_version.py'
29+
+versionfile_build ='numba/_version.py'

0 commit comments

Comments
 (0)