diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_ctypes.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_ctypes.py index 9a35def6ce..be89b8ce89 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_ctypes.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_ctypes.py @@ -39,6 +39,7 @@ import ctypes import os.path import struct +import sys from tests.cpyext import CPyExtTestCase, CPyExtType @@ -225,3 +226,27 @@ class MyLargeStruct(ctypes.Structure): assert result.num7 == 42 finally: os.chdir(original_cwd) + + +def test_void_p(): + assert ctypes.c_void_p(True).value == ctypes.c_void_p(1).value + assert ctypes.c_void_p(False).value == ctypes.c_void_p(0).value + assert ctypes.c_void_p(2**128 - 1).value == ctypes.c_void_p(2**64 - 1).value + try: + ctypes.c_void_p(2**128 - 1) + except TypeError as e: + assert "cannot be converted to pointer" in str(e) + + +def test_meson_windows_detect_native_arch() -> str: + if sys.platform != 'win32': + return + process_arch = ctypes.c_ushort() + native_arch = ctypes.c_ushort() + kernel32 = ctypes.windll.kernel32 + process = ctypes.c_void_p(kernel32.GetCurrentProcess()) + try: + if kernel32.IsWow64Process2(process, ctypes.byref(process_arch), ctypes.byref(native_arch)): + assert native_arch.value == 0x8664, "only amd64 supported by GraalPy on Windows" + except AttributeError as e: + assert "Unknown identifier: IsWow64Process2" in str(e) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py index 6591ed359f..e96723941d 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py @@ -172,6 +172,11 @@ def foo(**kwargs): assert foo(a=5, b=6) == {'a': 1, 'b': 1} + d = dict.fromkeys({'a': 1, 'b': 2, 'c': 3}) + assert len(d) == 3 + assert set(d.keys()) == {'a', 'b', 'c'} + assert set(d.values()) == {None} + def test_init(): d = dict(a=1, b=2, c=3) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py b/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py index 934c2edcdb..b84ffd29b8 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -879,7 +879,6 @@ def test_sysconf_names(self): self.assertIn('SC_CLK_TCK', os.sysconf_names) def test_sysconf(self): - self.assertGreaterEqual(os.sysconf('SC_CLK_TCK'), 0) with self.assertRaisesRegex(TypeError, 'strings or integers'): os.sysconf(object()) with self.assertRaisesRegex(ValueError, 'unrecognized'): @@ -892,6 +891,17 @@ def test_sysconf(self): else: assert False + # constants taken from POSIX where defined + self.assertGreaterEqual(os.sysconf('SC_ARG_MAX'), 4096) + self.assertGreaterEqual(os.sysconf('SC_CHILD_MAX'), 25) + self.assertGreaterEqual(os.sysconf('SC_LOGIN_NAME_MAX'), 9) + self.assertGreaterEqual(os.sysconf('SC_CLK_TCK'), 0) + self.assertGreaterEqual(os.sysconf('SC_OPEN_MAX'), 20) + self.assertGreaterEqual(os.sysconf('SC_PAGESIZE'), 1) + os.sysconf('SC_SEM_NSEMS_MAX') # returns -1 on my linux box, just check it's there + self.assertGreaterEqual(os.sysconf('SC_PHYS_PAGES'), 1) + self.assertGreaterEqual(os.sysconf('SC_NPROCESSORS_CONF'), 1) + if __name__ == '__main__': unittest.main() diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java index b870ff47d4..0d7146f58f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -62,6 +62,7 @@ public void afterRegistration(AfterRegistrationAccess access) { // Register runtime reflection here, not in a config, so it can be easily disabled String[] reflectiveClasses = new String[]{ + // BouncyCastle looks up the classes below "org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings", "org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings", "org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings", @@ -160,9 +161,37 @@ public void afterRegistration(AfterRegistrationAccess access) { for (String name : reflectiveClasses) { try { - RuntimeReflection.register(Class.forName(name).getConstructor()); - } catch (NoSuchMethodException | SecurityException | ClassNotFoundException e) { - throw new RuntimeException("Could not register " + name + " constructor for reflective access!", e); + RuntimeReflection.register(Class.forName(name)); + RuntimeReflection.register(Class.forName(name).getConstructors()); + } catch (SecurityException | ClassNotFoundException e) { + throw new RuntimeException("Could not register " + name + " for reflective access!", e); + } + } + + // SSLBasicKeyDerivation looks up the classes below reflectively since jdk-25+23 + // See https://github.com/openjdk/jdk/pull/24393 + reflectiveClasses = new String[]{ + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA256", + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA384", + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA512", + "sun.security.pkcs11.P11HKDF", + }; + for (String name : reflectiveClasses) { + try { + Class.forName(name); + } catch (SecurityException | ClassNotFoundException e) { + return; + } + } + // For backwards compatibility with older JDKs, we only do this if we found + // all those classes + Security.addProvider(Security.getProvider("SunJCE")); + for (String name : reflectiveClasses) { + try { + RuntimeReflection.register(Class.forName(name)); + RuntimeReflection.register(Class.forName(name).getConstructors()); + } catch (SecurityException | ClassNotFoundException e) { + throw new RuntimeException("Could not register " + name + " for reflective access!", e); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index dade4225da..67b859e10a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -68,8 +69,6 @@ import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary; import com.oracle.graal.python.builtins.objects.bytes.BytesNodes; import com.oracle.graal.python.builtins.objects.bytes.PBytes; -import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage; -import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemNode; @@ -92,6 +91,8 @@ import com.oracle.graal.python.lib.PyNumberIndexNode; import com.oracle.graal.python.lib.PyOSFSPathNode; import com.oracle.graal.python.lib.PyObjectAsFileDescriptor; +import com.oracle.graal.python.lib.PyObjectGetAttr; +import com.oracle.graal.python.lib.PyObjectGetItem; import com.oracle.graal.python.lib.PyObjectSizeNode; import com.oracle.graal.python.lib.PyUnicodeCheckNode; import com.oracle.graal.python.nodes.ErrorMessages; @@ -101,6 +102,7 @@ import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonClinicBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode; @@ -252,7 +254,21 @@ public void initialize(Python3Core core) { PythonLanguage language = core.getLanguage(); addBuiltinConstant("_have_functions", PFactory.createList(language, haveFunctions.toArray())); addBuiltinConstant("environ", PFactory.createDict(language)); - addBuiltinConstant("sysconf_names", PFactory.createDict(language)); + + LinkedHashMap sysconfigNames = new LinkedHashMap<>(); + for (IntConstant name : PosixConstants.sysconfigNames) { + if (name.defined) { + // add the constant without the leading underscore + String pythonName; + if (name.name.startsWith("_")) { + pythonName = name.name.substring(1); + } else { + pythonName = name.name; + } + sysconfigNames.put(pythonName, name.getValueIfDefined()); + } + } + addBuiltinConstant("sysconf_names", PFactory.createDictFromMap(language, sysconfigNames)); StructSequence.initType(core, STAT_RESULT_DESC); StructSequence.initType(core, STATVFS_RESULT_DESC); @@ -346,9 +362,6 @@ public void postInitialize(Python3Core core) { Object environAttr = posix.getAttribute(tsLiteral("environ")); ((PDict) environAttr).setDictStorage(environ.getDictStorage()); - PDict sysconfNamesAttr = (PDict) posix.getAttribute(tsLiteral("sysconf_names")); - sysconfNamesAttr.setDictStorage(HashingStorageNodes.HashingStorageCopy.executeUncached(SysconfNode.SYSCONF_NAMES)); - if (posixLib.getBackend(posixSupport).toJavaStringUncached().equals("java")) { posix.setAttribute(toTruffleStringUncached("statvfs"), PNone.NO_VALUE); posix.setAttribute(toTruffleStringUncached("geteuid"), PNone.NO_VALUE); @@ -2863,50 +2876,43 @@ static int getCpuCount() { } } - @Builtin(name = "sysconf", minNumOfPositionalArgs = 1, parameterNames = {"name"}) + @Builtin(name = "sysconf", minNumOfPositionalArgs = 2, parameterNames = {"$self", "name"}, declaresExplicitSelf = true) @GenerateNodeFactory - abstract static class SysconfNode extends PythonUnaryBuiltinNode { + abstract static class SysconfNode extends PythonBinaryBuiltinNode { - public static final TruffleString T_SC_CLK_TCK = tsLiteral("SC_CLK_TCK"); - public static final TruffleString T_SC_NPROCESSORS_ONLN = tsLiteral("SC_NPROCESSORS_ONLN"); - public static final int SC_CLK_TCK = 2; - public static final int SC_NPROCESSORS_ONLN = 84; - public static final EconomicMapStorage SYSCONF_NAMES = EconomicMapStorage.create(); - static { - // TODO populate from constants - SYSCONF_NAMES.putUncached(T_SC_CLK_TCK, SC_CLK_TCK); - SYSCONF_NAMES.putUncached(T_SC_NPROCESSORS_ONLN, SC_NPROCESSORS_ONLN); - } + private static final TruffleString T_SYSCONF_NAMES = tsLiteral("sysconf_names"); @Specialization - static int sysconf(VirtualFrame frame, Object arg, + static long sysconf(VirtualFrame frame, PythonModule self, Object arg, @Bind("this") Node inliningTarget, @Cached PyLongCheckNode longCheckNode, @Cached PyLongAsIntNode asIntNode, @Cached PyUnicodeCheckNode unicodeCheckNode, - @Cached HashingStorageNodes.HashingStorageGetItem getItem, + @Cached PyObjectGetAttr getAttr, + @Cached PyObjectGetItem getItem, @Cached PRaiseNode raiseNode, + @Bind PythonContext context, + @CachedLibrary("context.getPosixSupport()") PosixSupportLibrary posixLib, @Cached PConstructAndRaiseNode.Lazy constructAndRaiseNode) { int id; if (longCheckNode.execute(inliningTarget, arg)) { id = asIntNode.execute(frame, inliningTarget, arg); } else if (unicodeCheckNode.execute(inliningTarget, arg)) { - Object idObj = getItem.execute(frame, inliningTarget, SYSCONF_NAMES, arg); - if (idObj instanceof Integer idInt) { - id = idInt; - } else { + try { + Object sysconfigNamesObject = getAttr.execute(frame, inliningTarget, self, T_SYSCONF_NAMES); + Object idObj = getItem.execute(frame, inliningTarget, sysconfigNamesObject, arg); + id = asIntNode.execute(frame, inliningTarget, idObj); + } catch (PException e) { throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.UNRECOGNIZED_CONF_NAME); } } else { throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.CONFIGURATION_NAMES_MUST_BE_STRINGS_OR_INTEGERS); } - if (id == SC_CLK_TCK) { - return 100; // it's 100 on most default kernel configs. TODO: use real value through - // NFI - } else if (id == SC_NPROCESSORS_ONLN) { - return CpuCountNode.getCpuCount(); + try { + return posixLib.sysconf(context.getPosixSupport(), id); + } catch (PosixException e) { + throw constructAndRaiseNode.get(inliningTarget).raiseOSErrorFromPosixException(frame, e); } - throw constructAndRaiseNode.get(inliningTarget).raiseOSError(frame, OSErrorEnum.EINVAL); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CFieldBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CFieldBuiltins.java index 0a8ccb7867..858baed7f6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CFieldBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CFieldBuiltins.java @@ -725,19 +725,14 @@ static Object Z_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, O @Specialization(guards = "setfunc == P_set") static Object P_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object value, @SuppressWarnings("unused") int size, @Bind("this") Node inliningTarget, - @Exclusive @Cached PyLongCheckNode longCheckNode, @Exclusive @Cached PointerNodes.PointerFromLongNode pointerFromLongNode, - @Exclusive @Cached PointerNodes.WritePointerNode writePointerNode, - @Exclusive @Cached PRaiseNode raiseNode) { + @Exclusive @Cached PointerNodes.WritePointerNode writePointerNode) { Pointer valuePtr; if (value == PNone.NONE) { valuePtr = Pointer.NULL; - } else if (longCheckNode.execute(inliningTarget, value)) { - valuePtr = pointerFromLongNode.execute(inliningTarget, value); } else { - throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.CANNOT_BE_CONVERTED_TO_POINTER); + valuePtr = pointerFromLongNode.execute(inliningTarget, value); } - writePointerNode.execute(inliningTarget, ptr, valuePtr); return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java index bd13e21cf8..5ce63f3b5b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java @@ -41,9 +41,12 @@ package com.oracle.graal.python.builtins.modules.ctypes.memory; import static com.oracle.graal.python.builtins.PythonBuiltinClassType.NotImplementedError; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OverflowError; import static com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.WCHAR_T_SIZE; import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR; +import java.math.BigInteger; + import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.ByteArrayStorage; import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.LongPointerStorage; import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.MemoryBlock; @@ -58,14 +61,15 @@ import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes; import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions; +import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.nodes.ErrorMessages; import com.oracle.graal.python.nodes.PRaiseNode; -import com.oracle.graal.python.nodes.util.CastToJavaUnsignedLongNode; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.util.PythonUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateCached; @@ -790,11 +794,36 @@ static Pointer doNativeVoidPtr(PythonNativeVoidPtr value) { return Pointer.nativeMemory(pointerObject); } - @Fallback - static Pointer doLong(Node inliningTarget, Object value, - @Cached CastToJavaUnsignedLongNode cast) { - long pointer = cast.execute(inliningTarget, value); - return Pointer.nativeMemory(pointer); + @Specialization + static Pointer doBool(Node inliningTarget, boolean value) { + return Pointer.nativeMemory(value ? 1 : 0); + } + + @Specialization + static Pointer doLong(Node inliningTarget, long value) { + return Pointer.nativeMemory(value); + } + + @Specialization + static Pointer doPInt(Node inliningTarget, PInt value) { + return Pointer.nativeMemory(value.longValue()); + } + + @Specialization + @TruffleBoundary + @InliningCutoff + static Pointer doGeneric(Node inliningTarget, Object value, + @CachedLibrary(limit = "1") InteropLibrary lib) { + if (lib.fitsInBigInteger(value)) { + BigInteger bi; + try { + bi = lib.asBigInteger(value); + return doLong(inliningTarget, bi.longValue()); + } catch (UnsupportedMessageException e) { + // fall through to error + } + } + throw PRaiseNode.raiseStatic(inliningTarget, OverflowError, ErrorMessages.CANNOT_BE_CONVERTED_TO_POINTER); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java index 2af6cc4b4d..473590e5d6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java @@ -45,6 +45,10 @@ import static com.oracle.graal.python.nodes.BuiltinNames.J_SHA3; import static com.oracle.graal.python.nodes.BuiltinNames.T_HASHLIB; import static com.oracle.graal.python.nodes.BuiltinNames.T_SHA3; +import static com.oracle.graal.python.nodes.ErrorMessages.ITERATION_VALUE_IS_TOO_GREAT; +import static com.oracle.graal.python.nodes.ErrorMessages.ITERATION_VALUE_MUST_BE_GREATER_THAN_ZERO; +import static com.oracle.graal.python.nodes.ErrorMessages.KEY_LENGTH_MUST_BE_GREATER_THAN_ZERO; +import static com.oracle.graal.python.nodes.ErrorMessages.UNSUPPORTED_HASH_TYPE; import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING; import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached; import static com.oracle.graal.python.util.PythonUtils.tsLiteral; @@ -60,6 +64,12 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.jcajce.provider.util.DigestFactory; + import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.ArgumentClinic; import com.oracle.graal.python.builtins.Builtin; @@ -68,6 +78,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.modules.hashlib.HashlibModuleBuiltinsClinicProviders.NewNodeClinicProviderGen; +import com.oracle.graal.python.builtins.modules.hashlib.HashlibModuleBuiltinsClinicProviders.Pbkdf2HmacNodeClinicProviderGen; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary; import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary; @@ -75,7 +86,9 @@ import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.ssl.CertUtils; +import com.oracle.graal.python.lib.PyLongAsLongNode; import com.oracle.graal.python.nodes.ErrorMessages; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PRaiseNode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromPythonObjectNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -89,6 +102,7 @@ import com.oracle.graal.python.nodes.util.CastToTruffleStringNode; import com.oracle.graal.python.runtime.IndirectCallData; import com.oracle.graal.python.runtime.object.PFactory; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -103,6 +117,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.InlinedConditionProfile; import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.api.strings.TruffleString.CodeRange; @@ -451,4 +466,77 @@ static int getFips() { return 0; } } + + @Builtin(name = "pbkdf2_hmac", minNumOfPositionalArgs = 4, parameterNames = {"hash_name", "password", "salt", "iterations", "dklen"}) + @GenerateNodeFactory + @ArgumentClinic(name = "hash_name", conversion = ArgumentClinic.ClinicConversion.TString) + @ArgumentClinic(name = "password", conversion = ArgumentClinic.ClinicConversion.ReadableBuffer) + @ArgumentClinic(name = "salt", conversion = ArgumentClinic.ClinicConversion.ReadableBuffer) + @ArgumentClinic(name = "iterations", conversion = ArgumentClinic.ClinicConversion.Long) + abstract static class Pbkdf2HmacNode extends PythonClinicBuiltinNode { + @Override + protected ArgumentClinicProvider getArgumentClinic() { + return Pbkdf2HmacNodeClinicProviderGen.INSTANCE; + } + + @Specialization(limit = "3") + static Object pbkdf2(VirtualFrame frame, TruffleString hashName, Object password, Object salt, long iterations, Object dklenObj, + @Bind("this") Node inliningTarget, + @Bind PythonLanguage language, + @CachedLibrary("password") PythonBufferAccessLibrary passwordLib, + @CachedLibrary("salt") PythonBufferAccessLibrary saltLib, + @Cached PyLongAsLongNode asLongNode, + @Cached InlinedConditionProfile noDklenProfile, + @Cached TruffleString.ToJavaStringNode toJavaStringNode, + @Cached PRaiseNode raiseNode) { + try { + Digest digest = getDigest(toJavaStringNode.execute(hashName)); + if (digest == null) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.UnsupportedDigestmodError, UNSUPPORTED_HASH_TYPE, hashName); + } + if (iterations < 1) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.ValueError, ITERATION_VALUE_MUST_BE_GREATER_THAN_ZERO); + } + if (iterations > Integer.MAX_VALUE) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.OverflowError, ITERATION_VALUE_IS_TOO_GREAT); + } + long dklen; + if (noDklenProfile.profile(inliningTarget, PGuards.isPNone(dklenObj))) { + dklen = digest.getDigestSize(); + } else { + dklen = asLongNode.execute(frame, inliningTarget, dklenObj); + } + dklen *= Byte.SIZE; + if (dklen < 1) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.ValueError, KEY_LENGTH_MUST_BE_GREATER_THAN_ZERO); + } + if (dklen > Integer.MAX_VALUE) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.OverflowError, ITERATION_VALUE_IS_TOO_GREAT); + } + byte[] passwordBytes = passwordLib.getInternalOrCopiedExactByteArray(password); + byte[] saltBytes = saltLib.getInternalOrCopiedExactByteArray(salt); + return PFactory.createBytes(language, generate(digest, passwordBytes, saltBytes, (int) iterations, (int) dklen)); + } finally { + passwordLib.release(password); + saltLib.release(salt); + } + } + + @TruffleBoundary + private static Digest getDigest(String name) { + name = name.toLowerCase(); + return DigestFactory.getDigest(NAME_MAPPINGS.getOrDefault(name, name)); + } + + @TruffleBoundary + private static byte[] generate(Digest digest, byte[] password, byte[] salt, int iterations, int dklen) { + PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(digest); + generator.init(password, salt, iterations); + CipherParameters cipherParameters = generator.generateDerivedParameters(dklen); + if (!(cipherParameters instanceof KeyParameter keyParameter)) { + throw CompilerDirectives.shouldNotReachHere("unexpected cipher parameters"); + } + return keyParameter.getKey(); + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/pickle/PUnpickler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/pickle/PUnpickler.java index f3596ea0ba..b56af84398 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/pickle/PUnpickler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/pickle/PUnpickler.java @@ -769,7 +769,7 @@ protected HashingStorage getClonedHashingStorage(VirtualFrame frame, Object obj) CompilerDirectives.transferToInterpreterAndInvalidate(); getHashingStorageNode = insert(HashingCollectionNodes.GetClonedHashingStorageNode.create()); } - return getHashingStorageNode.doNoValueCached(frame, obj); + return getHashingStorageNode.getForSetsCached(frame, obj); } private void setItem(VirtualFrame frame, Object object, Object key, Object value) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/PythonBufferAccessLibrary.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/PythonBufferAccessLibrary.java index 2b24992b99..3aa07edd15 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/PythonBufferAccessLibrary.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/PythonBufferAccessLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -277,6 +277,21 @@ public final byte[] getInternalOrCopiedByteArray(Object receiver) { } } + /** + * Get a byte array representing the buffer contents. Unlike + * {@link #getInternalOrCopiedByteArray(Object)}, always returns a byte array with length equal + * to the buffer size, making a copy if necessary. Do not write into the byte array. + */ + public final byte[] getInternalOrCopiedExactByteArray(Object receiver) { + if (hasInternalByteArray(receiver)) { + byte[] r = getInternalByteArray(receiver); + if (r.length == getBufferLength(receiver)) { + return r; + } + } + return getCopiedByteArray(receiver); + } + /** * Read a single byte from the buffer. Bounds checks are responsibility of the caller. * diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java index 1708f625e8..edd88d1e13 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java @@ -55,12 +55,14 @@ import com.oracle.graal.python.builtins.objects.dict.DictNodes; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.dict.PDictView; +import com.oracle.graal.python.builtins.objects.set.PBaseSet; import com.oracle.graal.python.lib.IteratorExhausted; import com.oracle.graal.python.lib.PyIterNextNode; import com.oracle.graal.python.lib.PyObjectGetIter; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.util.CastToTruffleStringNode; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -121,8 +123,8 @@ abstract static class SetValueHashingStorageNode extends PNodeWithContext { @Specialization static HashingStorage doEconomicStorage(VirtualFrame frame, Node inliningTarget, EconomicMapStorage map, Object value, - @Cached PutUnsafeNode putNode, - @Cached InlinedLoopConditionProfile loopProfile) { + @Shared("putNode") @Cached PutUnsafeNode putNode, + @Shared("loopProfile") @Cached InlinedLoopConditionProfile loopProfile) { // We want to avoid calling __hash__() during map.put map.setValueForAllKeys(frame, inliningTarget, value, putNode, loopProfile); return map; @@ -134,14 +136,25 @@ static HashingStorage doGeneric(VirtualFrame frame, Node inliningTarget, Hashing @Cached HashingStorageSetItem setItem, @Cached HashingStorageGetIterator getIterator, @Cached HashingStorageIteratorNext itNext, - @Cached HashingStorageIteratorKey itKey) { + @Cached HashingStorageIteratorKey itKey, + @Shared("putNode") @Cached PutUnsafeNode putNode, + @Shared("loopProfile") @Cached InlinedLoopConditionProfile loopProfile) { HashingStorageIterator it = getIterator.execute(inliningTarget, map); - HashingStorage storage = map; while (itNext.execute(inliningTarget, map, it)) { - Object key = itKey.execute(inliningTarget, storage, it); - storage = setItem.execute(frame, inliningTarget, storage, key, value); + Object key = itKey.execute(inliningTarget, map, it); + HashingStorage newStorage = setItem.execute(frame, inliningTarget, map, key, value); + if (newStorage != map) { + // when the storage changes, the iterator state is not a reliable cursor + // anymore and we need to restart. + if (newStorage instanceof EconomicMapStorage mapStorage) { + mapStorage.setValueForAllKeys(frame, inliningTarget, value, putNode, loopProfile); + return mapStorage; + } else { + throw CompilerDirectives.shouldNotReachHere("We only generalize to EconomicMapStorage"); + } + } } - return storage; + return map; } protected static boolean isEconomicMapStorage(Object o) { @@ -150,42 +163,62 @@ protected static boolean isEconomicMapStorage(Object o) { } /** - * Gets clone of the keys of the storage with all values either set to given value or with no - * guarantees about the values if {@link PNone#NO_VALUE} is passed as {@code value}. + * Gets clone of the keys of the storage with all values set to given value or (when used to + * create a set or frozenset) to NO_VALUE. */ @GenerateInline(inlineByDefault = true) public abstract static class GetClonedHashingStorageNode extends PNodeWithContext { - public abstract HashingStorage execute(VirtualFrame frame, Node inliningTarget, Object iterator, Object value); + protected abstract HashingStorage execute(VirtualFrame frame, Node inliningTarget, Object iterator, Object value); + + /** + * Gets clone of the keys of the storage with all values either set to given value or, if + * that is PNone.NO_VALUE, all values set to PNone.NONE. Use this method to clone into a + * dict or other object where the values may be accessible from Python to avoid a) + * PNone.NO_VALUE leaking to Python. + */ + public final HashingStorage getForDictionaries(VirtualFrame frame, Node inliningTarget, Object iterator, Object value) { + return execute(frame, inliningTarget, iterator, value == PNone.NO_VALUE ? PNone.NONE : value); + } - public final HashingStorage doNoValue(VirtualFrame frame, Node inliningTarget, Object iterator) { + /** + * Gets a clone of the keys of the storage with all values set to NO_VALUE. This must be + * used *only* to create new storages for use in sets and frozensets where the values cannot + * be accessed from user code. + */ + public final HashingStorage getForSets(VirtualFrame frame, Node inliningTarget, Object iterator) { return execute(frame, inliningTarget, iterator, PNone.NO_VALUE); } - public final HashingStorage doNoValueCached(VirtualFrame frame, Object iterator) { + /** + * IMPORTANT: Only for sets and frozensets. + * + * @see #getForSets(VirtualFrame, Node, Object) + */ + public final HashingStorage getForSetsCached(VirtualFrame frame, Object iterator) { return execute(frame, null, iterator, PNone.NO_VALUE); } - @Specialization(guards = "isNoValue(value)") - static HashingStorage doHashingCollectionNoValue(Node inliningTarget, PHashingCollection other, @SuppressWarnings("unused") Object value, - @Shared("copyNode") @Cached HashingStorageCopy copyNode) { + // This for cloning sets (we come here from doNoValue or doNoValueCached). If we clone from + // some other PHashingCollection, we would hold on to keys in the sets, and if we were to + // clone for some other PHashingCollection (not PBaseSet), we might leak NO_VALUE into user + // code. + @Specialization(guards = "isNoValue(givenValue)") + static HashingStorage doSet(Node inliningTarget, PBaseSet other, @SuppressWarnings("unused") Object givenValue, + @Cached HashingStorageCopy copyNode) { return copyNode.execute(inliningTarget, other.getDictStorage()); } - @Specialization(guards = "isNoValue(value)") - static HashingStorage doPDictKeyViewNoValue(Node inliningTarget, PDictView.PDictKeysView other, Object value, - @Shared("copyNode") @Cached HashingStorageCopy copyNode) { - return copyNode.execute(inliningTarget, other.getWrappedStorage()); - } - - @Specialization(guards = "!isNoValue(value)") - static HashingStorage doHashingCollection(VirtualFrame frame, PHashingCollection other, Object value, + @Specialization(replaces = "doSet") + static HashingStorage doHashingCollection(VirtualFrame frame, PHashingCollection other, Object givenValue, @Shared @Cached(inline = false) GetClonedHashingCollectionNode hashingCollectionNode) { + Object value = givenValue == PNone.NO_VALUE ? PNone.NONE : givenValue; return hashingCollectionNode.execute(frame, other.getDictStorage(), value); } - @Specialization(guards = "!isNoValue(value)") - static HashingStorage doPDictView(VirtualFrame frame, PDictView.PDictKeysView other, Object value, + @Specialization + static HashingStorage doPDictView(VirtualFrame frame, PDictView.PDictKeysView other, Object givenValue, @Shared @Cached(inline = false) GetClonedHashingCollectionNode hashingCollectionNode) { + Object value = givenValue == PNone.NO_VALUE ? PNone.NONE : givenValue; return hashingCollectionNode.execute(frame, other.getWrappedStorage(), value); } @@ -282,7 +315,7 @@ static HashingStorage doPDictView(PDictView.PDictKeysView other) { @InliningCutoff static HashingStorage doGeneric(VirtualFrame frame, Node inliningTarget, Object other, @Cached GetClonedHashingStorageNode getHashingStorageNode) { - return getHashingStorageNode.doNoValue(frame, inliningTarget, other); + return getHashingStorageNode.getForSets(frame, inliningTarget, other); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java index 8685da8ab6..3343033f36 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java @@ -606,7 +606,7 @@ static Object doKeys(VirtualFrame frame, @SuppressWarnings("unused") Object cls, @SuppressWarnings("unused") @Cached IsSameTypeNode isSameTypeNode, @Cached HashingCollectionNodes.GetClonedHashingStorageNode getHashingStorageNode, @Bind PythonLanguage language) { - HashingStorage s = getHashingStorageNode.execute(frame, inliningTarget, iterable, value); + HashingStorage s = getHashingStorageNode.getForDictionaries(frame, inliningTarget, iterable, value); return PFactory.createDict(language, s); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/FrozenSetBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/FrozenSetBuiltins.java index b49fc0b6c5..f4beb6e2c3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/FrozenSetBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/FrozenSetBuiltins.java @@ -119,7 +119,7 @@ static PFrozenSet frozensetIterable(VirtualFrame frame, Object cls, Object itera @Cached HashingCollectionNodes.GetClonedHashingStorageNode getHashingStorageNode, @Bind PythonLanguage language, @Cached TypeNodes.GetInstanceShape getInstanceShape) { - HashingStorage storage = getHashingStorageNode.doNoValue(frame, inliningTarget, iterable); + HashingStorage storage = getHashingStorageNode.getForSets(frame, inliningTarget, iterable); return PFactory.createFrozenSet(language, cls, getInstanceShape.execute(cls), storage); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/SetBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/SetBuiltins.java index 900c542c3e..baf225ebf0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/SetBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/SetBuiltins.java @@ -155,7 +155,7 @@ static PNone doNoValue(PSet self, @SuppressWarnings("unused") PNone iterable, static PNone doGeneric(VirtualFrame frame, PSet self, Object iterable, @Bind("this") Node inliningTarget, @Cached HashingCollectionNodes.GetClonedHashingStorageNode getHashingStorageNode) { - HashingStorage storage = getHashingStorageNode.doNoValue(frame, inliningTarget, iterable); + HashingStorage storage = getHashingStorageNode.getForSets(frame, inliningTarget, iterable); self.setDictStorage(storage); return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/types/UnionTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/types/UnionTypeBuiltins.java index b12f409a51..a39de9cde7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/types/UnionTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/types/UnionTypeBuiltins.java @@ -180,7 +180,7 @@ static long hash(VirtualFrame frame, PUnionType self, @Cached PyObjectHashNode hashNode, @Cached HashingCollectionNodes.GetClonedHashingStorageNode getHashingStorageNode, @Bind PythonLanguage language) { - PFrozenSet argSet = PFactory.createFrozenSet(language, getHashingStorageNode.doNoValue(frame, inliningTarget, self.getArgs())); + PFrozenSet argSet = PFactory.createFrozenSet(language, getHashingStorageNode.getForSets(frame, inliningTarget, self.getArgs())); return hashNode.execute(frame, inliningTarget, argSet); } } @@ -273,8 +273,8 @@ static boolean eq(VirtualFrame frame, PUnionType self, PUnionType other, RichCmp @Cached HashingCollectionNodes.GetClonedHashingStorageNode getHashingStorageNode, @Cached PyObjectRichCompareBool eqNode, @Bind PythonLanguage language) { - PFrozenSet argSet1 = PFactory.createFrozenSet(language, getHashingStorageNode.doNoValue(frame, inliningTarget, self.getArgs())); - PFrozenSet argSet2 = PFactory.createFrozenSet(language, getHashingStorageNode.doNoValue(frame, inliningTarget, other.getArgs())); + PFrozenSet argSet1 = PFactory.createFrozenSet(language, getHashingStorageNode.getForSets(frame, inliningTarget, self.getArgs())); + PFrozenSet argSet2 = PFactory.createFrozenSet(language, getHashingStorageNode.getForSets(frame, inliningTarget, other.getArgs())); return eqNode.execute(frame, inliningTarget, argSet1, argSet2, op); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java index a1b91ac609..42d0352eed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java @@ -448,6 +448,10 @@ public abstract class ErrorMessages { public static final TruffleString ISINSTANCE_ARG_2_MUST_BE_TYPE_OR_TUPLE_OF_TYPE = tsLiteral("isinstance() arg 2 must be a type or tuple of types (was: %s)"); public static final TruffleString ISSUBCLASS_MUST_BE_CLASS_OR_TUPLE = tsLiteral("issubclass() arg 2 must be a class or tuple of classes"); public static final TruffleString ITER_V_MUST_BE_CALLABLE = tsLiteral("iter(v, w): v must be callable"); + public static final TruffleString ITERATION_VALUE_MUST_BE_GREATER_THAN_ZERO = tsLiteral("iteration value must be greater than 0."); + public static final TruffleString ITERATION_VALUE_IS_TOO_GREAT = tsLiteral("iteration value is too great."); + public static final TruffleString KEY_LENGTH_MUST_BE_GREATER_THAN_ZERO = tsLiteral("key length must be greater than 0."); + public static final TruffleString KEY_LENGTH_IS_TOO_GREAT = tsLiteral("key length is too great."); public static final TruffleString KEYWORD_NAMES_MUST_BE_STR_GOT_P = tsLiteral("keyword names must be str, get %p"); public static final TruffleString KEYWORDS_S_MUST_BE_STRINGS = tsLiteral("keywords must be strings"); public static final TruffleString KLASS_ARG_IS_NOT_HOST_OBJ = tsLiteral("klass argument '%p' is not a host object"); @@ -777,6 +781,7 @@ public abstract class ErrorMessages { public static final TruffleString UNSIGNED_BYTE_INT_GREATER_THAN_MAX = tsLiteral("unsigned byte integer is greater than maximum"); public static final TruffleString UNSIGNED_BYTE_INT_LESS_THAN_MIN = tsLiteral("unsigned byte integer is less than minimum"); public static final TruffleString UNSUPPORTED_FORMAT_CHAR_AT_INDEX = tsLiteral("unsupported format character '%c' (0x%x) at index %d"); + public static final TruffleString UNSUPPORTED_HASH_TYPE = tsLiteral("unsupported hash type %s"); public static final TruffleString UNSUPPORTED_INSTANCEOF = tsLiteral("unsupported instanceof(%p, %p)"); public static final TruffleString UNSUPPORTED_LOCALE_SETTING = tsLiteral("unsupported locale setting"); public static final TruffleString UNSUPPORTED_OBJ_IN = tsLiteral("unsupported object in '%s'"); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/EmulatedPosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/EmulatedPosixSupport.java index 99eb13093c..d8d92c94d5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/EmulatedPosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/EmulatedPosixSupport.java @@ -997,6 +997,36 @@ public int[] getTerminalSize(int fd) throws PosixException { return new int[]{context.getOption(PythonOptions.TerminalWidth), context.getOption(PythonOptions.TerminalHeight)}; } + @ExportMessage + @TruffleBoundary + public long sysconf(int name) throws PosixException { + // Constants derived from POSIX specs or common kernel configs + if (name == PosixConstants._SC_ARG_MAX.value) { + return 4096; + } else if (name == PosixConstants._SC_CHILD_MAX.value) { + return 25; + } else if (name == PosixConstants._SC_LOGIN_NAME_MAX.value) { + return 255; + } else if (name == PosixConstants._SC_CLK_TCK.value) { + return 100; + } else if (name == PosixConstants._SC_OPEN_MAX.value) { + return 20; + } else if (name == PosixConstants._SC_PAGESIZE.value) { + return 4096; + } else if (name == PosixConstants._SC_PAGE_SIZE.value) { + return 4096; + } else if (name == PosixConstants._SC_SEM_NSEMS_MAX.value) { + return 32; + } else if (name == PosixConstants._SC_PHYS_PAGES.value) { + return Runtime.getRuntime().totalMemory() / 4096; + } else if (name == PosixConstants._SC_NPROCESSORS_CONF.value) { + return Runtime.getRuntime().availableProcessors(); + } else if (name == PosixConstants._SC_NPROCESSORS_ONLN.value) { + return Runtime.getRuntime().availableProcessors(); + } + throw posixException(OSErrorEnum.EINVAL); + } + @ExportMessage public long[] fstatat(int dirFd, Object path, boolean followSymlinks, @Bind("$node") Node inliningTarget, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/LoggingPosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/LoggingPosixSupport.java index 2c023ccfbc..042b782152 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/LoggingPosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/LoggingPosixSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -361,6 +361,17 @@ final int[] getTerminalSize(int fd, } } + @ExportMessage + final long sysconf(int name, + @CachedLibrary("this.delegate") PosixSupportLibrary lib) throws PosixException { + logEnter("sysconf", "%d", name); + try { + return logExit("sysconf", "%s", lib.sysconf(delegate, name)); + } catch (PosixException e) { + throw logException("sysconf", e); + } + } + @ExportMessage final long[] fstatat(int dirFd, Object pathname, boolean followSymlinks, @CachedLibrary("this.delegate") PosixSupportLibrary lib) throws PosixException { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NFIPosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NFIPosixSupport.java index 4405a4f3fe..ba4279a864 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NFIPosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NFIPosixSupport.java @@ -304,6 +304,8 @@ private enum PosixNativeFunction { call_ioctl_bytes("(sint32, uint64, [sint8]):sint32"), call_ioctl_int("(sint32, uint64, sint32):sint32"), + call_sysconf("(sint32):sint64"), + crypt("([sint8], [sint8]):sint64"); private final String signature; @@ -749,6 +751,19 @@ public int[] getTerminalSize(int fd, return size; } + @ExportMessage + public long sysconf(int name, + @Shared("invoke") @Cached InvokeNativeFunction invokeNode) throws PosixException { + long result = invokeNode.callLong(this, PosixNativeFunction.call_sysconf, name); + if (result == -1) { + int errno = getErrno(invokeNode); + if (errno != 0) { + throw newPosixException(invokeNode, errno); + } + } + return result; + } + @ExportMessage public long[] fstatat(int dirFd, Object pathname, boolean followSymlinks, @Shared("invoke") @Cached InvokeNativeFunction invokeNode) throws PosixException { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstants.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstants.java index ce050b11e4..b67dedc9fa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstants.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -332,6 +332,39 @@ public final class PosixConstants { public static final OptionalIntConstant IPV6_RECVPATHMTU; public static final OptionalIntConstant IPV6_TCLASS; public static final OptionalIntConstant IPV6_USE_MIN_MTU; + public static final MandatoryIntConstant _SC_ARG_MAX; + public static final MandatoryIntConstant _SC_CHILD_MAX; + public static final OptionalIntConstant _SC_HOST_NAME_MAX; + public static final MandatoryIntConstant _SC_LOGIN_NAME_MAX; + public static final OptionalIntConstant _SC_NGROUPS_MAX; + public static final MandatoryIntConstant _SC_CLK_TCK; + public static final MandatoryIntConstant _SC_OPEN_MAX; + public static final MandatoryIntConstant _SC_PAGESIZE; + public static final MandatoryIntConstant _SC_PAGE_SIZE; + public static final OptionalIntConstant _SC_RE_DUP_MAX; + public static final OptionalIntConstant _SC_STREAM_MAX; + public static final OptionalIntConstant _SC_SYMLOOP_MAX; + public static final OptionalIntConstant _SC_TTY_NAME_MAX; + public static final OptionalIntConstant _SC_TZNAME_MAX; + public static final OptionalIntConstant _SC_VERSION; + public static final OptionalIntConstant _SC_BC_BASE_MAX; + public static final OptionalIntConstant _SC_BC_DIM_MAX; + public static final OptionalIntConstant _SC_BC_SCALE_MAX; + public static final OptionalIntConstant _SC_BC_STRING_MAX; + public static final OptionalIntConstant _SC_COLL_WEIGHTS_MAX; + public static final OptionalIntConstant _SC_EXPR_NEST_MAX; + public static final OptionalIntConstant _SC_LINE_MAX; + public static final OptionalIntConstant _SC_2_VERSION; + public static final OptionalIntConstant _SC_2_C_DEV; + public static final OptionalIntConstant _SC_2_FORT_DEV; + public static final OptionalIntConstant _SC_2_FORT_RUN; + public static final OptionalIntConstant _SC_2_LOCALEDEF; + public static final OptionalIntConstant _SC_2_SW_DEV; + public static final MandatoryIntConstant _SC_SEM_NSEMS_MAX; + public static final MandatoryIntConstant _SC_PHYS_PAGES; + public static final OptionalIntConstant _SC_AVPHYS_PAGES; + public static final MandatoryIntConstant _SC_NPROCESSORS_CONF; + public static final MandatoryIntConstant _SC_NPROCESSORS_ONLN; public static final IntConstant[] openFlags; public static final IntConstant[] fileType; @@ -355,6 +388,7 @@ public final class PosixConstants { public static final IntConstant[] socketOptions; public static final IntConstant[] tcpOptions; public static final IntConstant[] ipv6Options; + public static final IntConstant[] sysconfigNames; static { Registry reg = Registry.create(); @@ -614,6 +648,39 @@ public final class PosixConstants { IPV6_RECVPATHMTU = reg.createOptionalInt("IPV6_RECVPATHMTU"); IPV6_TCLASS = reg.createOptionalInt("IPV6_TCLASS"); IPV6_USE_MIN_MTU = reg.createOptionalInt("IPV6_USE_MIN_MTU"); + _SC_ARG_MAX = reg.createMandatoryInt("_SC_ARG_MAX"); + _SC_CHILD_MAX = reg.createMandatoryInt("_SC_CHILD_MAX"); + _SC_HOST_NAME_MAX = reg.createOptionalInt("_SC_HOST_NAME_MAX"); + _SC_LOGIN_NAME_MAX = reg.createMandatoryInt("_SC_LOGIN_NAME_MAX"); + _SC_NGROUPS_MAX = reg.createOptionalInt("_SC_NGROUPS_MAX"); + _SC_CLK_TCK = reg.createMandatoryInt("_SC_CLK_TCK"); + _SC_OPEN_MAX = reg.createMandatoryInt("_SC_OPEN_MAX"); + _SC_PAGESIZE = reg.createMandatoryInt("_SC_PAGESIZE"); + _SC_PAGE_SIZE = reg.createMandatoryInt("_SC_PAGE_SIZE"); + _SC_RE_DUP_MAX = reg.createOptionalInt("_SC_RE_DUP_MAX"); + _SC_STREAM_MAX = reg.createOptionalInt("_SC_STREAM_MAX"); + _SC_SYMLOOP_MAX = reg.createOptionalInt("_SC_SYMLOOP_MAX"); + _SC_TTY_NAME_MAX = reg.createOptionalInt("_SC_TTY_NAME_MAX"); + _SC_TZNAME_MAX = reg.createOptionalInt("_SC_TZNAME_MAX"); + _SC_VERSION = reg.createOptionalInt("_SC_VERSION"); + _SC_BC_BASE_MAX = reg.createOptionalInt("_SC_BC_BASE_MAX"); + _SC_BC_DIM_MAX = reg.createOptionalInt("_SC_BC_DIM_MAX"); + _SC_BC_SCALE_MAX = reg.createOptionalInt("_SC_BC_SCALE_MAX"); + _SC_BC_STRING_MAX = reg.createOptionalInt("_SC_BC_STRING_MAX"); + _SC_COLL_WEIGHTS_MAX = reg.createOptionalInt("_SC_COLL_WEIGHTS_MAX"); + _SC_EXPR_NEST_MAX = reg.createOptionalInt("_SC_EXPR_NEST_MAX"); + _SC_LINE_MAX = reg.createOptionalInt("_SC_LINE_MAX"); + _SC_2_VERSION = reg.createOptionalInt("_SC_2_VERSION"); + _SC_2_C_DEV = reg.createOptionalInt("_SC_2_C_DEV"); + _SC_2_FORT_DEV = reg.createOptionalInt("_SC_2_FORT_DEV"); + _SC_2_FORT_RUN = reg.createOptionalInt("_SC_2_FORT_RUN"); + _SC_2_LOCALEDEF = reg.createOptionalInt("_SC_2_LOCALEDEF"); + _SC_2_SW_DEV = reg.createOptionalInt("_SC_2_SW_DEV"); + _SC_SEM_NSEMS_MAX = reg.createMandatoryInt("_SC_SEM_NSEMS_MAX"); + _SC_PHYS_PAGES = reg.createMandatoryInt("_SC_PHYS_PAGES"); + _SC_AVPHYS_PAGES = reg.createOptionalInt("_SC_AVPHYS_PAGES"); + _SC_NPROCESSORS_CONF = reg.createMandatoryInt("_SC_NPROCESSORS_CONF"); + _SC_NPROCESSORS_ONLN = reg.createMandatoryInt("_SC_NPROCESSORS_ONLN"); openFlags = new IntConstant[]{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_NOCTTY, O_NDELAY, O_DSYNC, O_CLOEXEC, O_SYNC, O_DIRECT, O_RSYNC, O_TMPFILE, O_TEMPORARY, O_DIRECTORY, O_BINARY, O_TEXT, O_XATTR, O_LARGEFILE, O_SHLOCK, O_EXLOCK, O_EXEC, O_SEARCH, O_PATH, O_TTY_INIT}; @@ -646,6 +713,10 @@ public final class PosixConstants { ipv6Options = new IntConstant[]{IPV6_JOIN_GROUP, IPV6_LEAVE_GROUP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IPV6_CHECKSUM, IPV6_DONTFRAG, IPV6_DSTOPTS, IPV6_HOPLIMIT, IPV6_HOPOPTS, IPV6_NEXTHOP, IPV6_PATHMTU, IPV6_PKTINFO, IPV6_RECVDSTOPTS, IPV6_RECVHOPLIMIT, IPV6_RECVHOPOPTS, IPV6_RECVPKTINFO, IPV6_RECVRTHDR, IPV6_RECVTCLASS, IPV6_RTHDR, IPV6_RTHDRDSTOPTS, IPV6_RTHDR_TYPE_0, IPV6_RECVPATHMTU, IPV6_TCLASS, IPV6_USE_MIN_MTU}; + sysconfigNames = new IntConstant[]{_SC_ARG_MAX, _SC_CHILD_MAX, _SC_HOST_NAME_MAX, _SC_LOGIN_NAME_MAX, _SC_NGROUPS_MAX, _SC_CLK_TCK, _SC_OPEN_MAX, _SC_PAGESIZE, _SC_PAGE_SIZE, _SC_RE_DUP_MAX, + _SC_STREAM_MAX, _SC_SYMLOOP_MAX, _SC_TTY_NAME_MAX, _SC_TZNAME_MAX, _SC_VERSION, _SC_BC_BASE_MAX, _SC_BC_DIM_MAX, _SC_BC_SCALE_MAX, _SC_BC_STRING_MAX, _SC_COLL_WEIGHTS_MAX, + _SC_EXPR_NEST_MAX, _SC_LINE_MAX, _SC_2_VERSION, _SC_2_C_DEV, _SC_2_FORT_DEV, _SC_2_FORT_RUN, _SC_2_LOCALEDEF, _SC_2_SW_DEV, _SC_SEM_NSEMS_MAX, _SC_PHYS_PAGES, _SC_AVPHYS_PAGES, + _SC_NPROCESSORS_CONF, _SC_NPROCESSORS_ONLN}; } // end generated by gen_native_cfg.py // @formatter:on diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsDarwin.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsDarwin.java index 2ae39c5780..a6ac5ddfe8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsDarwin.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsDarwin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -242,5 +242,22 @@ static void getConstants(PosixConstants.Registry constants) { constants.put("IPV6_RECVTCLASS", 35); constants.put("IPV6_RTHDR_TYPE_0", 0); constants.put("IPV6_TCLASS", 36); + constants.put("_SC_ARG_MAX", 1); + constants.put("_SC_CHILD_MAX", 2); + constants.put("_SC_LOGIN_NAME_MAX", 73); + constants.put("_SC_NGROUPS_MAX", 4); + constants.put("_SC_CLK_TCK", 3); + constants.put("_SC_OPEN_MAX", 5); + constants.put("_SC_PAGESIZE", 29); + constants.put("_SC_PAGE_SIZE", 29); + constants.put("_SC_RE_DUP_MAX", 16); + constants.put("_SC_STREAM_MAX", 26); + constants.put("_SC_TTY_NAME_MAX", 101); + constants.put("_SC_TZNAME_MAX", 27); + constants.put("_SC_VERSION", 8); + constants.put("_SC_SEM_NSEMS_MAX", 49); + constants.put("_SC_PHYS_PAGES", 200); + constants.put("_SC_NPROCESSORS_CONF", 83); + constants.put("_SC_NPROCESSORS_ONLN", 84); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsLinux.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsLinux.java index 97c90ef632..8b82c45635 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsLinux.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsLinux.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -40,8 +40,8 @@ */ package com.oracle.graal.python.runtime; -// Auto generated by gen_native_cfg.py at 2023-10-20 10:35:45.655413 -// on Linux arisu 6.5.7-100.fc37.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Oct 11 03:54:39 UTC 2023 x86_64 x86_64 +// Auto generated by gen_native_cfg.py at 2025-05-20 13:24:18.395774 +// on Linux FrankTheTank 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 class PosixConstantsLinux { private PosixConstantsLinux() { @@ -290,5 +290,38 @@ static void getConstants(PosixConstants.Registry constants) { constants.put("IPV6_RTHDR_TYPE_0", 0); constants.put("IPV6_RECVPATHMTU", 60); constants.put("IPV6_TCLASS", 67); + constants.put("_SC_ARG_MAX", 0); + constants.put("_SC_CHILD_MAX", 1); + constants.put("_SC_HOST_NAME_MAX", 180); + constants.put("_SC_LOGIN_NAME_MAX", 71); + constants.put("_SC_NGROUPS_MAX", 3); + constants.put("_SC_CLK_TCK", 2); + constants.put("_SC_OPEN_MAX", 4); + constants.put("_SC_PAGESIZE", 30); + constants.put("_SC_PAGE_SIZE", 30); + constants.put("_SC_RE_DUP_MAX", 44); + constants.put("_SC_STREAM_MAX", 5); + constants.put("_SC_SYMLOOP_MAX", 173); + constants.put("_SC_TTY_NAME_MAX", 72); + constants.put("_SC_TZNAME_MAX", 6); + constants.put("_SC_VERSION", 29); + constants.put("_SC_BC_BASE_MAX", 36); + constants.put("_SC_BC_DIM_MAX", 37); + constants.put("_SC_BC_SCALE_MAX", 38); + constants.put("_SC_BC_STRING_MAX", 39); + constants.put("_SC_COLL_WEIGHTS_MAX", 40); + constants.put("_SC_EXPR_NEST_MAX", 42); + constants.put("_SC_LINE_MAX", 43); + constants.put("_SC_2_VERSION", 46); + constants.put("_SC_2_C_DEV", 48); + constants.put("_SC_2_FORT_DEV", 49); + constants.put("_SC_2_FORT_RUN", 50); + constants.put("_SC_2_LOCALEDEF", 52); + constants.put("_SC_2_SW_DEV", 51); + constants.put("_SC_SEM_NSEMS_MAX", 32); + constants.put("_SC_PHYS_PAGES", 85); + constants.put("_SC_AVPHYS_PAGES", 86); + constants.put("_SC_NPROCESSORS_CONF", 83); + constants.put("_SC_NPROCESSORS_ONLN", 84); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsWin32.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsWin32.java index 076fa3e7b0..fd441c7f4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsWin32.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsWin32.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -215,5 +215,16 @@ static void getConstants(PosixConstants.Registry constants) { constants.put("IPV6_RECVTCLASS", 40); constants.put("IPV6_RTHDR", 32); constants.put("IPV6_TCLASS", 39); + constants.put("_SC_ARG_MAX", 0); + constants.put("_SC_CHILD_MAX", 1); + constants.put("_SC_LOGIN_NAME_MAX", 2); + constants.put("_SC_CLK_TCK", 3); + constants.put("_SC_OPEN_MAX", 4); + constants.put("_SC_PAGESIZE", 5); + constants.put("_SC_PAGE_SIZE", 5); + constants.put("_SC_SEM_NSEMS_MAX", 7); + constants.put("_SC_PHYS_PAGES", 8); + constants.put("_SC_NPROCESSORS_CONF", 9); + constants.put("_SC_NPROCESSORS_ONLN", 9); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixSupportLibrary.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixSupportLibrary.java index e92f0af5fc..0e91cfba18 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixSupportLibrary.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixSupportLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -125,6 +125,8 @@ public abstract class PosixSupportLibrary extends Library { public abstract int[] getTerminalSize(Object receiver, int fd) throws PosixException; + public abstract long sysconf(Object receiver, int name) throws PosixException; + // see stat_struct_to_longs in posix.c for the layout of the array public abstract long[] fstatat(Object receiver, int dirFd, Object pathname, boolean followSymlinks) throws PosixException; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PreInitPosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PreInitPosixSupport.java index 38033c0230..a4d36183e5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PreInitPosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PreInitPosixSupport.java @@ -319,6 +319,13 @@ final int[] getTerminalSize(int fd, return nativeLib.getTerminalSize(nativePosixSupport, fd); } + @ExportMessage + final long sysconf(int name, + @CachedLibrary("this.nativePosixSupport") PosixSupportLibrary nativeLib) throws PosixException { + checkNotInPreInitialization(); + return nativeLib.sysconf(nativePosixSupport, name); + } + @ExportMessage final long[] fstatat(int dirFd, Object pathname, boolean followSymlinks, @CachedLibrary("this.nativePosixSupport") PosixSupportLibrary nativeLib) throws PosixException { diff --git a/graalpython/lib-graalpython/patches/metadata.toml b/graalpython/lib-graalpython/patches/metadata.toml index 7ea3ebea50..84502ba38a 100644 --- a/graalpython/lib-graalpython/patches/metadata.toml +++ b/graalpython/lib-graalpython/patches/metadata.toml @@ -152,6 +152,14 @@ version = '>= 1.64.0' patch = 'grpcio-1.66.1.patch' license = 'Apache-2.0' +[[grpcio.rules]] +# Force re-cythonize + other fixes +# The rc version won't get matched by the version range above +version = '== 1.72.0rc1' +install-priority = 0 +patch = 'grpcio-1.66.1.patch' +license = 'Apache-2.0' + [[h2o.rules]] patch = 'h2o.patch' license = 'Apache-2.0' @@ -425,10 +433,19 @@ patch = 'prompt_toolkit.patch' license = 'BSD-3-Clause' [[protobuf.rules]] +patch = 'protobuf.patch' +license = 'BSD-3-Clause' +# There are 'none-any' wheels on pypi, this is only needed on sdists +dist-type = 'sdist' +install-priority = 0 + +[[protobuf.rules]] +# msimacek: This version doesn't exist, but the patch file is referenced from the tensorflow patch which I'm afraid to touch version = '== 3.21.9' -# Also referenced outside of pip from tensorflow patches patch = 'protobuf-3.21.9.patch' license = 'BSD-3-Clause' +dist-type = 'sdist' +install-priority = 0 [[psycopg2.rules]] version = '<= 2.9.9' @@ -763,6 +780,12 @@ patch = 'torch-2.4.1.patch' license = 'BSD-3-Clause' dist-type = 'sdist' +[[torch.rules]] +version = '== 2.7.0' +patch = 'torch-2.7.0.patch' +license = 'BSD-3-Clause' +dist-type = 'sdist' + [[torch.add-sources]] version = '1.13.1' url = 'https://github.com/pytorch/pytorch/releases/download/v1.13.1/pytorch-v1.13.1.tar.gz' @@ -775,9 +798,22 @@ url = 'https://github.com/pytorch/pytorch/releases/download/v2.2.1/pytorch-v2.2.%20version%20='2.4.1' url = 'https://github.com/pytorch/pytorch/releases/download/v2.4.1/pytorch-v2.4.1.tar.gz' +[[torch.add-sources]] +version = '2.7.0' +url = 'https://github.com/pytorch/pytorch/releases/download/v2.7.0/pytorch-v2.7.0.tar.gz' + +[[torchvision.rules]] +version = '== 0.22.0' +patch = 'torchvision-0.22.0.patch' +license = 'BSD-3-Clause' + +[[torchvision.add-sources]] +version = '0.19.1' +url = 'https://github.com/pytorch/vision/archive/refs/tags/v0.22.0.tar.gz' + [[torchvision.rules]] version = '== 0.19.1' -patch = 'torchvision-1.19.1.patch' +patch = 'torchvision-0.19.1.patch' license = 'BSD-3-Clause' [[torchvision.add-sources]] @@ -786,7 +822,7 @@ url = 'https://github.com/pytorch/vision/archive/refs/tags/v0.19.1.tar.gz' [[torchvision.rules]] version = '== 0.17.1' -patch = 'torchvision-1.17.1.patch' +patch = 'torchvision-0.17.1.patch' license = 'BSD-3-Clause' [[torchvision.add-sources]] diff --git a/graalpython/lib-graalpython/patches/numpy-1.26.4.patch b/graalpython/lib-graalpython/patches/numpy-1.26.4.patch index a42d76ba53..d382e5bf16 100644 --- a/graalpython/lib-graalpython/patches/numpy-1.26.4.patch +++ b/graalpython/lib-graalpython/patches/numpy-1.26.4.patch @@ -92,15 +92,3 @@ index 1c59bf3..519fabc 100644 volatile char NPY_UNUSED(c) = *(char *)param; } -diff --git a/vendored-meson/meson/mesonbuild/utils/universal.py b/vendored-meson/meson/mesonbuild/utils/universal.py -index 1694912..a555fe3 100644 ---- a/vendored-meson/meson/mesonbuild/utils/universal.py -+++ b/vendored-meson/meson/mesonbuild/utils/universal.py -@@ -727,6 +727,7 @@ def windows_detect_native_arch() -> str: - """ - if sys.platform != 'win32': - return '' -+ return 'amd64' # Workaround for GraalPy bug on Windows with kernel32.GetCurrentProcess() - try: - import ctypes - process_arch = ctypes.c_ushort() diff --git a/graalpython/lib-graalpython/patches/numpy-2.0.0.patch b/graalpython/lib-graalpython/patches/numpy-2.0.0.patch index a381cefd59..4df9996c99 100644 --- a/graalpython/lib-graalpython/patches/numpy-2.0.0.patch +++ b/graalpython/lib-graalpython/patches/numpy-2.0.0.patch @@ -105,15 +105,3 @@ index 1c59bf3..519fabc 100644 volatile char NPY_UNUSED(c) = *(char *)param; } -diff --git a/vendored-meson/meson/mesonbuild/utils/universal.py b/vendored-meson/meson/mesonbuild/utils/universal.py -index 1694912..a555fe3 100644 ---- a/vendored-meson/meson/mesonbuild/utils/universal.py -+++ b/vendored-meson/meson/mesonbuild/utils/universal.py -@@ -727,6 +727,7 @@ def windows_detect_native_arch() -> str: - """ - if sys.platform != 'win32': - return '' -+ return 'amd64' # Workaround for GraalPy bug on Windows with kernel32.GetCurrentProcess() - try: - import ctypes - process_arch = ctypes.c_ushort() diff --git a/graalpython/lib-graalpython/patches/protobuf.patch b/graalpython/lib-graalpython/patches/protobuf.patch new file mode 100644 index 0000000000..85b8bd50ac --- /dev/null +++ b/graalpython/lib-graalpython/patches/protobuf.patch @@ -0,0 +1,15 @@ +diff --git a/google/protobuf/internal/api_implementation.py b/google/protobuf/internal/api_implementation.py +index b40446b..48e684f 100644 +--- a/google/protobuf/internal/api_implementation.py ++++ b/google/protobuf/internal/api_implementation.py +@@ -70,8 +70,8 @@ if _implementation_type not in ('python', 'cpp', 'upb'): + 'supported. Please set to \'python\', \'cpp\' or ' + '\'upb\'.'.format(_implementation_type)) + +-if 'PyPy' in sys.version and _implementation_type == 'cpp': +- warnings.warn('PyPy does not work yet with cpp protocol buffers. ' ++if sys.implementation.name in ('pypy', 'graalpy') and _implementation_type == 'cpp': ++ warnings.warn('PyPy and GraalPy do not work yet with cpp protocol buffers. ' + 'Falling back to the python implementation.') + _implementation_type = 'python' + diff --git a/graalpython/lib-graalpython/patches/torch-2.4.1.patch b/graalpython/lib-graalpython/patches/torch-2.4.1.patch index caebd3aa86..3dc4d354e3 100644 --- a/graalpython/lib-graalpython/patches/torch-2.4.1.patch +++ b/graalpython/lib-graalpython/patches/torch-2.4.1.patch @@ -178,6 +178,19 @@ index f5fdbf155..d76176cb6 100644 class TestWrapperSubclassAliasing(TestCase): +diff --git a/third_party/fbgemm/CMakeLists.txt b/third_party/fbgemm/CMakeLists.txt +index 134523e7d..a00538e3c 100644 +--- a/third_party/fbgemm/CMakeLists.txt ++++ b/third_party/fbgemm/CMakeLists.txt +@@ -10,6 +10,8 @@ + + cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + ++add_compile_options(-Wno-error=maybe-uninitialized -Wno-error=uninitialized -Wno-error=restrict) ++ + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + + # Define function to extract filelists from defs.bzl file diff --git a/third_party/pybind11/include/pybind11/detail/common.h b/third_party/pybind11/include/pybind11/detail/common.h index 454e6061b..7feafc7d7 100644 --- a/third_party/pybind11/include/pybind11/detail/common.h @@ -537,20 +550,6 @@ index c301da982..a2668be20 100644 +const int THP_PyOpcode_Caches_size = 0; + +#endif // GraalPy change -diff --git a/torch/csrc/dynamo/extra_state.c b/torch/csrc/dynamo/extra_state.c -index cbe9ab37a..18740a0d8 100644 ---- a/torch/csrc/dynamo/extra_state.c -+++ b/torch/csrc/dynamo/extra_state.c -@@ -100,9 +100,6 @@ void destroy_extra_state(void* obj) { - } - - void set_extra_state(PyCodeObject* code, ExtraState* extra_state) { -- ExtraState* old_extra_state = get_extra_state(code); -- CHECK(extra_state == nullptr || old_extra_state != extra_state); -- _PyCode_SetExtra((PyObject*)code, extra_index, extra_state); - } - - ExtraState* init_and_set_extra_state(PyCodeObject* code) { diff --git a/torch/csrc/dynamo/eval_frame.c b/torch/csrc/dynamo/eval_frame.c index cbe9ab37a..18740a0d8 100644 --- a/torch/csrc/dynamo/eval_frame.c @@ -628,6 +627,24 @@ index cbe9ab37a..18740a0d8 100644 return module; } +diff --git a/torch/csrc/dynamo/extra_state.cpp b/torch/csrc/dynamo/extra_state.cpp +index 7c9b4be00..b8edbcfda 100644 +--- a/torch/csrc/dynamo/extra_state.cpp ++++ b/torch/csrc/dynamo/extra_state.cpp +@@ -65,11 +65,13 @@ void destroy_extra_state(void* obj) { + } + + void set_extra_state(PyCodeObject* code, ExtraState* extra_state) { ++#if 0 // GraalPy change + ExtraState* old_extra_state = get_extra_state(code); + CHECK( + old_extra_state == nullptr || old_extra_state == SKIP_CODE || + old_extra_state != extra_state); + _PyCode_SetExtra((PyObject*)code, extra_index, extra_state); ++#endif // GraalPy change + } + + ExtraState* init_and_set_extra_state(PyCodeObject* code) { diff --git a/torch/csrc/jit/python/python_tracer.cpp b/torch/csrc/jit/python/python_tracer.cpp index 92e6e2d3a..4d2ec0bfe 100644 --- a/torch/csrc/jit/python/python_tracer.cpp diff --git a/graalpython/lib-graalpython/patches/torch-2.7.0.patch b/graalpython/lib-graalpython/patches/torch-2.7.0.patch new file mode 100644 index 0000000000..54adc4d9df --- /dev/null +++ b/graalpython/lib-graalpython/patches/torch-2.7.0.patch @@ -0,0 +1,774 @@ +diff --git a/functorch/csrc/dim/dim.cpp b/functorch/csrc/dim/dim.cpp +index 23179ad0e..ad9dbdbf7 100644 +--- a/functorch/csrc/dim/dim.cpp ++++ b/functorch/csrc/dim/dim.cpp +@@ -22,7 +22,9 @@ PyObject* Dim_init() { + + #include "minpybind.h" + #include ++#if 0 // GraalPy change + #include ++#endif // GraalPy change + #include + #include + #include +@@ -40,7 +42,9 @@ PyObject* Dim_init() { + #if IS_PYTHON_3_11_PLUS + + #define Py_BUILD_CORE ++#if 0 // GraalPy change + #include "internal/pycore_opcode.h" ++#endif // GraalPy change + #undef Py_BUILD_CORE + #endif + +@@ -1458,6 +1462,7 @@ PyTypeObject Tensor::Type = { + + // dim() -------------------- + ++#if 0 // GraalPy change + static bool relevant_op(_Py_CODEUNIT c) { + switch(c) { + case STORE_NAME: +@@ -1469,6 +1474,7 @@ static bool relevant_op(_Py_CODEUNIT c) { + return false; + } + } ++#endif // GraalPy change + + static mpy::object create_dim(mpy::object name, mpy::handle size) { + auto d = Dim::create(std::move(name)); +@@ -1502,6 +1508,7 @@ static mpy::object create_dimlist(mpy::object name, mpy::handle size) { + #endif + + namespace{ ++#if 0 // GraalPy change + struct PyInstDecoder { + PyInstDecoder(PyCodeObject* code_object, int lasti) + : code_object_(code_object), code_(_PyCode_CODE(code_object)), offset_(lasti / sizeof(_Py_CODEUNIT)) {} +@@ -1547,6 +1554,7 @@ private: + _Py_CODEUNIT* code_; + int offset_; + }; ++#endif // GraalPy change + + template + static PyObject* _dims(PyObject *self, +@@ -1572,6 +1580,7 @@ static PyObject* _dims(PyObject *self, + } + } + ++#if 0 // GraalPy change + PyThreadState* state = PyThreadState_GET(); + auto f = mpy::obj::steal(PyThreadState_GetFrame(state)); + auto c = mpy::obj::steal(PyFrame_GetCode(f.ptr())); +@@ -1592,10 +1601,12 @@ static PyObject* _dims(PyObject *self, + found_ndims = decoder.oparg(); + decoder.next(); + } ++#endif // GraalPy change + + if (specified_ndims == -1) { + if (found_ndims == 0) { +- mpy::raise_error(PyExc_SyntaxError, "dims() must be assigned to a sequence of variable names or have argument n specified"); ++ // GraalPy change ++ mpy::raise_error(PyExc_SyntaxError, "dims() without arguments doesn't work on GraalPy, use the explicit dims(number) form"); + } + specified_ndims = found_ndims; + } +@@ -1605,14 +1616,18 @@ static PyObject* _dims(PyObject *self, + + auto genobject = [&](int i) -> mpy::object { + mpy::object name; ++#if 0 // GraalPy change + if (i < found_ndims) { + name = decoder.name(); + } ++#endif // GraalPy change + if (!name.ptr()) { + name = mpy::unicode_from_format("d%d", i); + found_ndims = 0; // once we fail at finding a name, we can find any more + } else { ++#if 0 // GraalPy change + decoder.next(); ++#endif // GraalPy change + } + return create_object(std::move(name), sizes != -1 ? mpy::sequence_view(py_sizes)[i] : mpy::handle(Py_None)); + }; +@@ -2059,12 +2074,12 @@ struct IndexingInfo { + IndexingInfo getsetitem_flat(Arena& A, TensorInfo self_info, Slice input, Slice keys, Slice values, bool has_dimpacks_or_none); + namespace{ + Slice as_slice(mpy::tuple_view tv) { +- PyObject** begin = &PyTuple_GET_ITEM(tv.ptr(),0); ++ PyObject** begin = PySequence_Fast_ITEMS(tv.ptr()); + return Slice((mpy::handle*)begin, (mpy::handle*) (begin + tv.size())); + } + + Slice as_slice(mpy::list_view tv) { +- PyObject** begin = &PyList_GET_ITEM(tv.ptr(),0); ++ PyObject** begin = PySequence_Fast_ITEMS(tv.ptr()); + return Slice((mpy::handle*)begin, (mpy::handle*) (begin + tv.size())); + } + +diff --git a/pyproject.toml b/pyproject.toml +index e84d980ff..649a53a0a 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -4,9 +4,11 @@ requires = [ + "wheel", + "astunparse", + "numpy", +- "ninja", ++ # GraalPy change: require ninja on the system, the wheel wrapper goes through python, making the build very slow ++ # "ninja", + "pyyaml", +- "cmake", ++ # GraalPy change: same as ninja ++ # "cmake", + "typing-extensions>=4.10.0", + "requests", + ] +diff --git a/test/test_overrides.py b/test/test_overrides.py +index cc7c904a1..1249f9cce 100644 +--- a/test/test_overrides.py ++++ b/test/test_overrides.py +@@ -1561,12 +1561,9 @@ class TestTorchFunctionMode(TestCase): + pass + + x = A(torch.randn(5)) +- with torch._C.DisableTorchFunctionSubclass(): +- g = torch._C._EnableTorchFunction() +- try: ++ with torch._C.DisableTorchFunctionSubclass(), \ ++ torch._C._EnableTorchFunction(): + self.assertIsInstance(torch.sum(x), A) +- finally: +- del g + + def test_disable_enable_torch_function_ctx(self): + class A(torch.Tensor): +diff --git a/test/test_python_dispatch.py b/test/test_python_dispatch.py +index 2e6bbd406..0c77b21f7 100644 +--- a/test/test_python_dispatch.py ++++ b/test/test_python_dispatch.py +@@ -2470,16 +2470,16 @@ def forward(self, x_1): + class TestPythonDispatcher(TestCase): + def test_basic(self): + x = torch.randn(2, requires_grad=True) +- r = torch._C._EnablePythonDispatcher() +- torch.add(x, x) ++ with torch._C._EnablePythonDispatcher(): ++ torch.add(x, x) + + def test_lstsq(self): + a = torch.randn(4, 3) + b = torch.rand(4, 3) + expected_shape = torch.linalg.lstsq(a, b).solution.shape +- r = torch._C._EnablePythonDispatcher() +- python_disp_shape = torch.linalg.lstsq(a, b).solution.shape +- self.assertEqual(expected_shape, python_disp_shape) ++ with torch._C._EnablePythonDispatcher(): ++ python_disp_shape = torch.linalg.lstsq(a, b).solution.shape ++ self.assertEqual(expected_shape, python_disp_shape) + + + class TestWrapperSubclassAliasing(TestCase): +diff --git a/third_party/fbgemm/CMakeLists.txt b/third_party/fbgemm/CMakeLists.txt +index 134523e7d..a00538e3c 100644 +--- a/third_party/fbgemm/CMakeLists.txt ++++ b/third_party/fbgemm/CMakeLists.txt +@@ -10,6 +10,8 @@ + + cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + ++add_compile_options(-Wno-error=maybe-uninitialized -Wno-error=uninitialized -Wno-error=restrict) ++ + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + + # Define function to extract filelists from defs.bzl file +diff --git a/third_party/pybind11/include/pybind11/detail/common.h b/third_party/pybind11/include/pybind11/detail/common.h +index c51d1d60b..3976dd32b 100644 +--- a/third_party/pybind11/include/pybind11/detail/common.h ++++ b/third_party/pybind11/include/pybind11/detail/common.h +@@ -299,7 +299,7 @@ PYBIND11_WARNING_DISABLE_MSVC(4505) + # define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED + #endif + +-#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) ++#if (defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) + # define PYBIND11_SIMPLE_GIL_MANAGEMENT + #endif + +diff --git a/third_party/pybind11/include/pybind11/detail/internals.h b/third_party/pybind11/include/pybind11/detail/internals.h +index 232bc32d8..acde741f2 100644 +--- a/third_party/pybind11/include/pybind11/detail/internals.h ++++ b/third_party/pybind11/include/pybind11/detail/internals.h +@@ -449,7 +449,7 @@ inline void translate_local_exception(std::exception_ptr p) { + + inline object get_python_state_dict() { + object state_dict; +-#if PYBIND11_INTERNALS_VERSION <= 4 || PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION) ++#if PYBIND11_INTERNALS_VERSION <= 4 || PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION) || defined(GRAALVM_PYTHON) + state_dict = reinterpret_borrow(PyEval_GetBuiltins()); + #else + # if PY_VERSION_HEX < 0x03090000 +diff --git a/third_party/pybind11/include/pybind11/detail/type_caster_base.h b/third_party/pybind11/include/pybind11/detail/type_caster_base.h +index e40e44ba6..e7b94aff2 100644 +--- a/third_party/pybind11/include/pybind11/detail/type_caster_base.h ++++ b/third_party/pybind11/include/pybind11/detail/type_caster_base.h +@@ -459,7 +459,7 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i + } + + inline PyThreadState *get_thread_state_unchecked() { +-#if defined(PYPY_VERSION) ++#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON) + return PyThreadState_GET(); + #elif PY_VERSION_HEX < 0x030D0000 + return _PyThreadState_UncheckedGet(); +diff --git a/third_party/pybind11/include/pybind11/eval.h b/third_party/pybind11/include/pybind11/eval.h +index bd5f981f5..ee271672d 100644 +--- a/third_party/pybind11/include/pybind11/eval.h ++++ b/third_party/pybind11/include/pybind11/eval.h +@@ -94,18 +94,18 @@ void exec(const char (&s)[N], object global = globals(), object local = object() + eval(s, std::move(global), std::move(local)); + } + +-#if defined(PYPY_VERSION) ++#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON) + template + object eval_file(str, object, object) { +- pybind11_fail("eval_file not supported in PyPy3. Use eval"); ++ pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval"); + } + template + object eval_file(str, object) { +- pybind11_fail("eval_file not supported in PyPy3. Use eval"); ++ pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval"); + } + template + object eval_file(str) { +- pybind11_fail("eval_file not supported in PyPy3. Use eval"); ++ pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval"); + } + #else + template +diff --git a/third_party/pybind11/include/pybind11/pybind11.h b/third_party/pybind11/include/pybind11/pybind11.h +index 949bc9bb4..6e17baa03 100644 +--- a/third_party/pybind11/include/pybind11/pybind11.h ++++ b/third_party/pybind11/include/pybind11/pybind11.h +@@ -573,8 +573,7 @@ protected: + // chain. + chain_start = rec; + rec->next = chain; +- auto rec_capsule +- = reinterpret_borrow(((PyCFunctionObject *) m_ptr)->m_self); ++ auto rec_capsule = reinterpret_borrow(PyCFunction_GET_SELF(m_ptr)); + rec_capsule.set_pointer(unique_rec.release()); + guarded_strdup.release(); + } else { +@@ -636,9 +635,15 @@ protected: + + /* Install docstring */ + auto *func = (PyCFunctionObject *) m_ptr; ++#if !defined(GRAALVM_PYTHON) + //std::free(const_cast(GraalPyCFunction_GetDoc((PyObject*)(func)))); + // Install docstring if it's non-empty (when at least one option is enabled) + GraalPyCFunction_SetDoc((PyObject*)(func), signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str())); ++#else ++ std::free(const_cast(GraalPyCFunction_GetDoc(m_ptr))); ++ GraalPyCFunction_SetDoc( ++ m_ptr, signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str())); ++#endif + + if (rec->is_method) { + m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr()); +@@ -2766,8 +2771,8 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char * + } + + /* Don't call dispatch code if invoked from overridden function. +- Unfortunately this doesn't work on PyPy. */ +-#if !defined(PYPY_VERSION) ++ Unfortunately this doesn't work on PyPy and GraalPy. */ ++#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON) + # if PY_VERSION_HEX >= 0x03090000 + PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); + if (frame != nullptr) { +diff --git a/third_party/pybind11/include/pybind11/pytypes.h b/third_party/pybind11/include/pybind11/pytypes.h +index 8052f2ed0..7aafab6dc 100644 +--- a/third_party/pybind11/include/pybind11/pytypes.h ++++ b/third_party/pybind11/include/pybind11/pytypes.h +@@ -643,7 +643,7 @@ struct error_fetch_and_normalize { + + bool have_trace = false; + if (m_trace) { +-#if !defined(PYPY_VERSION) ++#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON) + auto *tb = reinterpret_cast(m_trace.ptr()); + + // Get the deepest trace possible. +diff --git a/tools/build_pytorch_libs.py b/tools/build_pytorch_libs.py +index 5dd5a2219..357bf15d8 100644 +--- a/tools/build_pytorch_libs.py ++++ b/tools/build_pytorch_libs.py +@@ -86,6 +86,7 @@ def _create_build_env() -> dict[str, str]: + + + def read_nccl_pin() -> str: ++ return 'v2.26.5-1' + nccl_file = "nccl-cu12.txt" + if os.getenv("DESIRED_CUDA", "").startswith("11") or os.getenv( + "CUDA_VERSION", "" +@@ -120,7 +121,7 @@ def build_pytorch( + ) -> None: + my_env = _create_build_env() + checkout_nccl() +- build_test = not check_negative_env_flag("BUILD_TEST") ++ build_test = not check_negative_env_flag("BUILD_TEST", "OFF") + cmake.generate( + version, cmake_python_library, build_python, build_test, my_env, rerun_cmake + ) +diff --git a/tools/generate_torch_version.py b/tools/generate_torch_version.py +index a33ea171e..400ae922f 100644 +--- a/tools/generate_torch_version.py ++++ b/tools/generate_torch_version.py +@@ -50,6 +50,8 @@ def get_tag(pytorch_root: str | Path) -> str: + def get_torch_version(sha: str | None = None) -> str: + pytorch_root = Path(__file__).absolute().parent.parent + version = open(pytorch_root / "version.txt").read().strip() ++ # GraalPy change ++ return re.sub(r'a.*', '', version) + + if os.getenv("PYTORCH_BUILD_VERSION"): + assert os.getenv("PYTORCH_BUILD_NUMBER") is not None +diff --git a/torch/_dynamo/decorators.py b/torch/_dynamo/decorators.py +index b9009f729..52e851d7e 100644 +--- a/torch/_dynamo/decorators.py ++++ b/torch/_dynamo/decorators.py +@@ -94,7 +94,8 @@ def skip(fn=None): + return skip + fn = innermost_fn(fn) + assert callable(fn) +- skip_code(fn.__code__) ++ # GraalPy change ++ # skip_code(fn.__code__) + fn._torchdynamo_disable = True + return fn + +@@ -396,15 +397,16 @@ def substitute_in_graph( + + wildcard_sig = inspect.signature(lambda *args, **kwargs: None) + +- if ( +- sig_ident(original_sig) != sig_ident(traceable_sig) +- and sig_ident(original_sig) != sig_ident(wildcard_sig) +- and sig_ident(traceable_sig) != sig_ident(wildcard_sig) +- ): +- raise TypeError( +- f"Signature mismatch between {original_fn} and {traceable_fn}: " +- f"{original_sig} != {traceable_sig}" +- ) ++ # GraalPy change ++ # if ( ++ # sig_ident(original_sig) != sig_ident(traceable_sig) ++ # and sig_ident(original_sig) != sig_ident(wildcard_sig) ++ # and sig_ident(traceable_sig) != sig_ident(wildcard_sig) ++ # ): ++ # raise TypeError( ++ # f"Signature mismatch between {original_fn} and {traceable_fn}: " ++ # f"{original_sig} != {traceable_sig}" ++ # ) + + from torch._dynamo.guards import GuardBuilder + from torch._dynamo.trace_rules import ( +diff --git a/torch/_tensor_str.py b/torch/_tensor_str.py +index b13daaeba..0124d81b2 100644 +--- a/torch/_tensor_str.py ++++ b/torch/_tensor_str.py +@@ -705,6 +705,6 @@ def _functorch_wrapper_str_intern(tensor, *, tensor_contents=None): + + + def _str(self, *, tensor_contents=None): +- with torch.no_grad(), torch.utils._python_dispatch._disable_current_modes(): +- guard = torch._C._DisableFuncTorch() # noqa: F841 ++ with torch.no_grad(), torch.utils._python_dispatch._disable_current_modes(), \ ++ torch._C._DisableFuncTorch(): + return _str_intern(self, tensor_contents=tensor_contents) +diff --git a/torch/csrc/Generator.cpp b/torch/csrc/Generator.cpp +index ce2b4789e..74da13115 100644 +--- a/torch/csrc/Generator.cpp ++++ b/torch/csrc/Generator.cpp +@@ -266,7 +266,7 @@ static PyObject* THPGenerator_reduce(PyObject* _self, PyObject* noargs) { + static PyObject* THPGenerator_pickleSetState(PyObject* _self, PyObject* state) { + HANDLE_TH_ERRORS + THPGenerator_manualSeed(_self, PyTuple_GET_ITEM(state, 0)); +- auto& offset = PyTuple_GET_ITEM(state, 1); ++ PyObject* offset = PyTuple_GET_ITEM(state, 1); + if (offset != Py_None) { + THPGenerator_setOffset(_self, offset); + } +diff --git a/torch/csrc/Module.cpp b/torch/csrc/Module.cpp +index 1ac30fecf..53c5a8c32 100644 +--- a/torch/csrc/Module.cpp ++++ b/torch/csrc/Module.cpp +@@ -436,46 +436,16 @@ static PyObject* THPModule_addDocStr(PyObject* _unused, PyObject* args) { + doc_str = all_docs.back().c_str(); + } + +- if (Py_TYPE(obj) == &PyCFunction_Type) { +- PyCFunctionObject* f = (PyCFunctionObject*)obj; +- if (GraalPyCFunction_GetDoc((PyObject*)(f))) { +- return PyErr_Format( +- PyExc_RuntimeError, +- "function '%s' already has a docstring", +- _PyCFunction_GetMethodDef((PyObject*)(f))->ml_name); +- } +- GraalPyCFunction_SetDoc((PyObject*)(f), doc_str); +- } else if (strcmp(Py_TYPE(obj)->tp_name, "method_descriptor") == 0) { +- PyMethodDescrObject* m = (PyMethodDescrObject*)obj; +- if (m->d_method->ml_doc) { +- return PyErr_Format( +- PyExc_RuntimeError, +- "method '%s' already has a docstring", +- m->d_method->ml_name); +- } +- m->d_method->ml_doc = doc_str; +- } else if (strcmp(Py_TYPE(obj)->tp_name, "getset_descriptor") == 0) { +- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) +- PyGetSetDescrObject* m = (PyGetSetDescrObject*)obj; +- if (m->d_getset->doc) { +- return PyErr_Format( +- PyExc_RuntimeError, +- "attribute '%s' already has a docstring", +- m->d_getset->name); +- } +- m->d_getset->doc = doc_str; +- } else if (Py_TYPE(obj) == &PyType_Type) { +- PyTypeObject* t = (PyTypeObject*)obj; +- if (t->tp_doc) { +- return PyErr_Format( +- PyExc_RuntimeError, "Type '%s' already has a docstring", t->tp_name); +- } +- t->tp_doc = doc_str; +- } else { ++ // GraalPy change ++ if (PyObject_GetDoc(obj)) { + return PyErr_Format( +- PyExc_TypeError, +- "don't know how to add docstring to type '%s'", +- Py_TYPE(obj)->tp_name); ++ PyExc_RuntimeError, ++ "object '%100R' already has a docstring", ++ obj); ++ } ++ // GraalPy change ++ if (PyObject_SetDoc(obj, doc_str) < 0) { ++ return NULL; + } + + Py_INCREF(obj); +diff --git a/torch/csrc/autograd/python_variable_indexing.cpp b/torch/csrc/autograd/python_variable_indexing.cpp +index ae1780e66..018c0e03f 100644 +--- a/torch/csrc/autograd/python_variable_indexing.cpp ++++ b/torch/csrc/autograd/python_variable_indexing.cpp +@@ -140,25 +140,28 @@ inline Variable valueToTensor( + + static void recordSliceTrace(PyObject* obj) { + PySliceObject* sliceobj = (PySliceObject*)obj; +- if (THPVariable_Check(sliceobj->start)) { ++ PyObject* slicestart = PySlice_Start(sliceobj); ++ if (THPVariable_Check(slicestart)) { + torch::jit::tracer::ArgumentStash::stashValue( + std::string("start"), + 1, +- THPVariable_Unpack(sliceobj->start), ++ THPVariable_Unpack(slicestart), + torch::jit::IntType::get()); + } +- if (THPVariable_Check(sliceobj->stop)) { ++ PyObject* slicestop = PySlice_Stop(sliceobj); ++ if (THPVariable_Check(slicestop)) { + torch::jit::tracer::ArgumentStash::stashValue( + std::string("end"), + 1, +- THPVariable_Unpack(sliceobj->stop), ++ THPVariable_Unpack(slicestop), + torch::jit::IntType::get()); + } +- if (THPVariable_Check(sliceobj->step)) { ++ PyObject* slicestep = PySlice_Step(sliceobj); ++ if (THPVariable_Check(slicestep)) { + torch::jit::tracer::ArgumentStash::stashValue( + std::string("step"), + 1, +- THPVariable_Unpack(sliceobj->step), ++ THPVariable_Unpack(slicestep), + torch::jit::IntType::get()); + } + } +diff --git a/torch/csrc/autograd/python_variable_indexing.h b/torch/csrc/autograd/python_variable_indexing.h +index 7efab1dcf..67b3cf44e 100644 +--- a/torch/csrc/autograd/python_variable_indexing.h ++++ b/torch/csrc/autograd/python_variable_indexing.h +@@ -37,14 +37,15 @@ inline UnpackedSlice __PySlice_Unpack(PyObject* _r) { + return val; + }; + +- if (r->step == Py_None) { ++ PyObject* stepObj = PySlice_Step(r); ++ if (stepObj == Py_None) { + step_sym = c10::SymInt(1); + } else { +- if (torch::is_symint(r->step)) { +- step_sym = py::handle(r->step).cast(); ++ if (torch::is_symint(stepObj)) { ++ step_sym = py::handle(stepObj).cast(); + } else { + Py_ssize_t step = 0; +- if (!_PyEval_SliceIndex(r->step, &step)) { ++ if (!_PyEval_SliceIndex(stepObj, &step)) { + throw python_error(); + } + if (step == 0) { +@@ -56,27 +57,29 @@ inline UnpackedSlice __PySlice_Unpack(PyObject* _r) { + } + } + +- if (torch::is_symint(r->start)) { +- start_sym = py::handle(r->start).cast(); +- } else if (r->start == Py_None) { ++ PyObject* startObj = PySlice_Start(r); ++ if (torch::is_symint(startObj)) { ++ start_sym = py::handle(startObj).cast(); ++ } else if (startObj == Py_None) { + start_sym = c10::SymInt(step_sym < 0 ? PY_SSIZE_T_MAX : 0); + } else { + Py_ssize_t start = 0; +- if (!_PyEval_SliceIndex(r->start, &start)) { ++ if (!_PyEval_SliceIndex(startObj, &start)) { + throw python_error(); + } + start = clip_val(start); + start_sym = c10::SymInt(start); + } + +- if (torch::is_symint(r->stop)) { +- stop_sym = py::handle(r->stop).cast(); +- } else if (r->stop == Py_None) { ++ PyObject* stopObj = PySlice_Stop(r); ++ if (torch::is_symint(stopObj)) { ++ stop_sym = py::handle(stopObj).cast(); ++ } else if (stopObj == Py_None) { + stop_sym = c10::SymInt( + step_sym < 0 ? c10::SymInt::min_representable_int() : PY_SSIZE_T_MAX); + } else { + Py_ssize_t stop = 0; +- if (!_PyEval_SliceIndex(r->stop, &stop)) { ++ if (!_PyEval_SliceIndex(stopObj, &stop)) { + throw python_error(); + } + stop = clip_val(stop); +diff --git a/torch/csrc/dynamo/cpython_defs.c b/torch/csrc/dynamo/cpython_defs.c +index b68ef894a..0837d95be 100644 +--- a/torch/csrc/dynamo/cpython_defs.c ++++ b/torch/csrc/dynamo/cpython_defs.c +@@ -2,6 +2,7 @@ + #include + #include + ++#if 0 // GraalPy change + #if IS_PYTHON_3_11_PLUS + + #define Py_BUILD_CORE +@@ -349,7 +350,8 @@ THP_PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) + + #endif + +-#if IS_PYTHON_3_11_PLUS ++// GraalPy change ++// #if IS_PYTHON_3_11_PLUS + + const uint8_t* THP_PyOpcode_Caches = _PyOpcode_Caches; + const int THP_PyOpcode_Caches_size = sizeof(_PyOpcode_Caches) / sizeof(uint8_t); +diff --git a/torch/csrc/dynamo/eval_frame.c b/torch/csrc/dynamo/eval_frame.c +index 048bb4e2c..51a302293 100644 +--- a/torch/csrc/dynamo/eval_frame.c ++++ b/torch/csrc/dynamo/eval_frame.c +@@ -1,5 +1,7 @@ + #define PY_SSIZE_T_CLEAN ++#if 0 // GraalPy change + #include ++#endif // GraalPy change + #include + #include + #include +@@ -34,7 +36,8 @@ void eval_frame_callback_set(PyObject* obj) { + } + + // 3.14 Not supported at all. See cpython_defs.c for hints +-#if !(IS_PYTHON_3_14_PLUS) ++// GraalPy change ++#if 0 + + #define DECLARE_PYOBJ_ATTR(name) \ + static PyObject* THPPyInterpreterFrame_##name( \ +@@ -543,9 +546,15 @@ static PyObject* set_eval_frame( + Py_INCREF(old_callback); + + if (old_callback != Py_None && new_callback == Py_None) { +- decrement_working_threads(tstate, module); ++ // GraalPy change ++ PyErr_SetString(PyExc_NotImplementedError, "dynamo compilation is not supported on GraalPy"); ++ return NULL; ++ // decrement_working_threads(tstate, module); + } else if (old_callback == Py_None && new_callback != Py_None) { +- increment_working_threads(tstate, module); ++ // GraalPy change ++ PyErr_SetString(PyExc_NotImplementedError, "dynamo compilation is not supported on GraalPy"); ++ return NULL; ++ // increment_working_threads(tstate, module); + } + + Py_INCREF(new_callback); +@@ -600,7 +609,8 @@ static PyObject* reset_code(PyObject* dummy, PyObject* code) { + } + + // set_extra_state destroys the existing object on extra scratch space. +- set_extra_state((PyCodeObject*)code, NULL); ++ // GraalPy change ++ // set_extra_state((PyCodeObject*)code, NULL); + Py_RETURN_NONE; + } + +@@ -679,12 +689,14 @@ static struct PyModuleDef _module = { + #endif + + PyObject* torch_c_dynamo_eval_frame_init(void) { ++#if 0 // GraalPy change + extra_index = _PyEval_RequestCodeExtraIndex(destroy_extra_state); + if (extra_index < 0) { + PyErr_SetString( + PyExc_RuntimeError, "dynamo: unable to register extra index"); + return NULL; + } ++#endif + + int result = PyThread_tss_create(&eval_frame_callback_key); + CHECK(result == 0); +diff --git a/torch/csrc/dynamo/eval_frame_cpp.cpp b/torch/csrc/dynamo/eval_frame_cpp.cpp +index f029fec22..0104c1812 100644 +--- a/torch/csrc/dynamo/eval_frame_cpp.cpp ++++ b/torch/csrc/dynamo/eval_frame_cpp.cpp +@@ -9,6 +9,7 @@ + + const char* cache_lookup_profiler_str = "TorchDynamo Cache Lookup"; + ++#if 0 // GraalPy change + // Remember to update the type signature for DynamoCallbackFn.__call__ in + // torch/_dynamo/types.py if this function's signature changes. + static py::object dynamo_call_callback( +@@ -290,8 +291,10 @@ PyObject* dynamo__custom_eval_frame( + } + return eval_result; + } ++#endif // GraalPy change + + PyObject* set_code_exec_strategy(PyObject* dummy, PyObject* args) { ++#if 0 // GraalPy change + PyObject* code_obj = nullptr; + PyObject* strategy_obj = nullptr; + if (!PyArg_ParseTuple(args, "OO", &code_obj, &strategy_obj)) { +@@ -313,4 +316,8 @@ PyObject* set_code_exec_strategy(PyObject* dummy, PyObject* args) { + + extra_state_set_exec_strategy(extra, strategy); + Py_RETURN_NONE; ++#endif // GraalPy change ++ // GraalPy change ++ PyErr_SetString(PyExc_NotImplementedError, "dynamo compilation is not supported on GraalPy"); ++ return NULL; + } +diff --git a/torch/csrc/dynamo/extra_state.cpp b/torch/csrc/dynamo/extra_state.cpp +index 2e60816aa..a06c0c830 100644 +--- a/torch/csrc/dynamo/extra_state.cpp ++++ b/torch/csrc/dynamo/extra_state.cpp +@@ -101,9 +101,7 @@ void destroy_extra_state(void* obj) { + } + + void set_extra_state(PyCodeObject* code, ExtraState* extra_state) { +- ExtraState* old_extra_state = get_extra_state(code); +- CHECK(extra_state == nullptr || old_extra_state != extra_state); +- _PyCode_SetExtra((PyObject*)code, extra_index, extra_state); ++ // GraalPy change: removed + } + + ExtraState* init_and_set_extra_state(PyCodeObject* code) { +diff --git a/torch/csrc/dynamo/framelocals_mapping.cpp b/torch/csrc/dynamo/framelocals_mapping.cpp +index b839fb26f..b7853029f 100644 +--- a/torch/csrc/dynamo/framelocals_mapping.cpp ++++ b/torch/csrc/dynamo/framelocals_mapping.cpp +@@ -4,7 +4,9 @@ + #include + #include + ++#if 0 // GraalPy change + #include ++#endif // GraalPy change + + #if IS_PYTHON_3_11_PLUS + +@@ -26,6 +28,7 @@ FrameLocalsMapping::FrameLocalsMapping(FrameLocalsFrameType* frame) + PyCodeObject* co = F_CODE(frame); + _framelocals.resize(co->co_nlocalsplus, nullptr); + ++#if 0 // GraalPy change + if (!frame->stacktop) { + return; + } +@@ -65,9 +68,11 @@ FrameLocalsMapping::FrameLocalsMapping(FrameLocalsFrameType* frame) + // NOTE no need to move the instruction pointer to after COPY_FREE_VARS + // since we don't actually copy free vars from the closure to the frame + // localsplus. ++#endif // GraalPy change + } + + void FrameLocalsMapping::_realize_dict() { ++#if 0 // GraalPy change + _dict = py::dict(); + py::tuple framelocals_names = code_framelocals_names(_code_obj); + +@@ -78,11 +83,13 @@ void FrameLocalsMapping::_realize_dict() { + _dict[framelocals_names[i]] = _framelocals[i]; + } + } ++#endif // GraalPy change + } + + py::tuple code_framelocals_names(py::handle code) { + CHECK(PyCode_Check(code.ptr())); +- return py::cast(((PyCodeObject*)code.ptr())->co_localsplusnames); ++ // GraalPy change ++ return code.attr("co_varnames") + code.attr("co_cellvars") + code.attr("co_freevars"); + } + + #else +diff --git a/torch/csrc/jit/python/python_tracer.cpp b/torch/csrc/jit/python/python_tracer.cpp +index 876186743..041348257 100644 +--- a/torch/csrc/jit/python/python_tracer.cpp ++++ b/torch/csrc/jit/python/python_tracer.cpp +@@ -31,11 +31,15 @@ std::vector _pythonCallstack() { + while (nullptr != frame) { + auto code = THPCodeObjectPtr(PyFrame_GetCode(frame)); + size_t line = PyCode_Addr2Line(code.get(), PyFrame_GetLasti(frame)); +- std::string filename = THPUtils_unpackString(code->co_filename); +- std::string funcname = THPUtils_unpackString(code->co_name); ++ PyObject* filenameObj = PyCode_GetFileName(code); ++ std::string filename = THPUtils_unpackString(filenameObj); ++ PyObject* funcnameObj = PyCode_GetName(code); ++ std::string funcname = THPUtils_unpackString(funcnameObj); + auto source = std::make_shared(funcname, filename, line); + entries.emplace_back( + StackEntry{funcname, SourceRange(source, 0, funcname.size())}); ++ Py_DECREF(funcnameObj); ++ Py_DECREF(filenameObj); + auto new_frame = PyFrame_GetBack(frame); + Py_DECREF(frame); + frame = new_frame; diff --git a/graalpython/lib-graalpython/patches/torchvision-1.17.1.patch b/graalpython/lib-graalpython/patches/torchvision-0.17.1.patch similarity index 100% rename from graalpython/lib-graalpython/patches/torchvision-1.17.1.patch rename to graalpython/lib-graalpython/patches/torchvision-0.17.1.patch diff --git a/graalpython/lib-graalpython/patches/torchvision-1.19.1.patch b/graalpython/lib-graalpython/patches/torchvision-0.19.1.patch similarity index 100% rename from graalpython/lib-graalpython/patches/torchvision-1.19.1.patch rename to graalpython/lib-graalpython/patches/torchvision-0.19.1.patch diff --git a/graalpython/lib-graalpython/patches/torchvision-0.22.0.patch b/graalpython/lib-graalpython/patches/torchvision-0.22.0.patch new file mode 100644 index 0000000000..394bfe2399 --- /dev/null +++ b/graalpython/lib-graalpython/patches/torchvision-0.22.0.patch @@ -0,0 +1,14 @@ +diff --git a/setup.py b/setup.py +index a42aef6..a619588 100644 +--- a/setup.py ++++ b/setup.py +@@ -104,6 +104,9 @@ def get_requirements(): + # supported on a best-effort basis, we don't guarantee that this won't + # eventually break (and we don't test it.) + pytorch_dep += f">={version_pin_ge},<{version_pin_lt}" ++ else: ++ # GraalPy change ++ pytorch_dep += "==" + torch.__version__ + + requirements = [ + "numpy", diff --git a/graalpython/python-libposix/src/posix.c b/graalpython/python-libposix/src/posix.c index 29dc4132c7..64cb005ae9 100644 --- a/graalpython/python-libposix/src/posix.c +++ b/graalpython/python-libposix/src/posix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -1080,6 +1080,11 @@ int32_t call_ioctl_int(int32_t fd, uint64_t request, int32_t arg) { return ioctl(fd, request, (int)arg); } +int64_t call_sysconf(int32_t name) { + errno = 0; + return sysconf(name); +} + int32_t get_errno() { return errno; } diff --git a/scripts/gen_native_cfg.py b/scripts/gen_native_cfg.py index f7aee6d680..973bdaa3ea 100644 --- a/scripts/gen_native_cfg.py +++ b/scripts/gen_native_cfg.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -121,6 +121,7 @@ # `x` - int, appearing in hexadecimal in the generated source # `b` - boolean, will be true if the plaform is Linux (WTF?) # Column #3 - the name of the constant +# Comments can come after that starting with "//" constant_defs = ''' b HAVE_FUTIMENS b HAVE_UTIMENSAT @@ -429,6 +430,41 @@ * i IPV6_RECVPATHMTU * i IPV6_TCLASS * i IPV6_USE_MIN_MTU + +[sysconfigNames] // These names use some sensible overlapping default values for windows +0 i _SC_ARG_MAX // I made those required which are on both Mac and Linux +1 i _SC_CHILD_MAX +* i _SC_HOST_NAME_MAX +2 i _SC_LOGIN_NAME_MAX +* i _SC_NGROUPS_MAX +3 i _SC_CLK_TCK +4 i _SC_OPEN_MAX +5 i _SC_PAGESIZE +5 i _SC_PAGE_SIZE +* i _SC_RE_DUP_MAX +* i _SC_STREAM_MAX +* i _SC_SYMLOOP_MAX +* i _SC_TTY_NAME_MAX +* i _SC_TZNAME_MAX +* i _SC_VERSION +* i _SC_BC_BASE_MAX +* i _SC_BC_DIM_MAX +* i _SC_BC_SCALE_MAX +* i _SC_BC_STRING_MAX +* i _SC_COLL_WEIGHTS_MAX +* i _SC_EXPR_NEST_MAX +* i _SC_LINE_MAX +* i _SC_2_VERSION +* i _SC_2_C_DEV +* i _SC_2_FORT_DEV +* i _SC_2_FORT_RUN +* i _SC_2_LOCALEDEF +* i _SC_2_SW_DEV +7 i _SC_SEM_NSEMS_MAX +8 i _SC_PHYS_PAGES +* i _SC_AVPHYS_PAGES +9 i _SC_NPROCESSORS_CONF +9 i _SC_NPROCESSORS_ONLN ''' layout_defs = ''' @@ -461,7 +497,7 @@ ''' java_copyright = '''/* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -524,7 +560,7 @@ class PosixConstants{platform} {{ def parse_defs(): - regex = re.compile(r'\[(\w+)\]|(\*|u|\d?)\s*(\w+)\s+(\w+)') + regex = re.compile(r'(?:\[(\w+)\]|(\*|u|\d?)\s*(\w+)\s+(\w+))( *\/\/.*)?') current_group = [] groups = {} constants = [] @@ -678,7 +714,7 @@ def generate_posix_constants(constants, groups): defs = [] def add_constant(opt, typ, name): - prefix = 'Optional' if opt == "*" else 'Mandatory' + prefix = 'Optional' if opt else 'Mandatory' decls.append(f' public static final {prefix}{typ}Constant {name};\n') defs.append(f' {name} = reg.create{prefix}{typ}("{name}");\n') diff --git a/scripts/wheelbuilder/darwin/shapely.sh b/scripts/wheelbuilder/darwin/shapely.sh new file mode 100755 index 0000000000..4064af4fa0 --- /dev/null +++ b/scripts/wheelbuilder/darwin/shapely.sh @@ -0,0 +1,42 @@ +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if [ -n "$GITHUB_RUN_ID" ]; then + brew install geos +fi diff --git a/scripts/wheelbuilder/linux/shapely.sh b/scripts/wheelbuilder/linux/shapely.sh new file mode 100644 index 0000000000..8fd92732b3 --- /dev/null +++ b/scripts/wheelbuilder/linux/shapely.sh @@ -0,0 +1,42 @@ +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if [ -n "$GITHUB_RUN_ID" ]; then + dnf install -y libgeos-devel +fi