Skip to content

Commit 98d9629

Browse files
committed
[GR-59182] Begin feature freeze for the 24.2 release.
PullRequest: graalpython/3658
2 parents cc99233 + b94c39b commit 98d9629

File tree

703 files changed

+71778
-43405
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

703 files changed

+71778
-43405
lines changed

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,25 @@ language runtime. The main focus is on user-observable behavior of the engine.
99
* When calling a method on a foreign object in Python code, Python methods are now prioritized over foreign members.
1010
* Added `polyglot.register_interop_type` and `@polyglot.interop_type` to define custom Python methods for a given foreign class/type. See [the documentation](https://github.com/oracle/graalpython/blob/master/docs/user/Interoperability.md#the-interoperability-extension-api) for more information.
1111
* Foreign objects are now given a Python class corresponding to their interop traits.
12-
* Foreign lists now inherit from Python `list`, foreign dictionaries from `dict`, foreign strings from `str`, foreign iterators from `iterator`, foreign exceptions from `BaseException`, foreign numbers from `ForeignNumberType` and foreign none/null from `NoneType`.
12+
* Foreign lists now inherit from Python `list`, foreign dictionaries from `dict`, foreign strings from `str`, foreign iterators from `iterator`, foreign exceptions from `BaseException`, foreign numbers from `polyglot.ForeignNumber`, foreign booleans from `polyglot.ForeignBoolean`, and foreign null values from `NoneType`.
1313
* This means all Python methods of these types are available on the corresponding foreign objects, which behave as close as possible as if they were Python objects.
1414
* See [the documentation](https://github.com/oracle/graalpython/blob/master/docs/user/Interoperability.md#interacting-with-foreign-objects-from-python-scripts) for more information.
1515
* Remove support for running with Sulong managed both in embeddings as well as through the `graalpy-managed` launcher.
1616
* Rewrite wheelbuilder to be easier to use and contribute to. This version is now the same we run internally to build publishable wheels for some platforms we support, so the community can build the same wheels on their own hardware easily if desired.
1717
* `pip` is now able to fetch newer versions of GraalPy patches for third-party packages from `graalpython` GitHub repository, allowing us to add new patches to released versions.
1818
* The patch repository can be overridden using `PIP_GRAALPY_PATCHES_URL` environment variable, which can point to a local path or a URL. It can be disabled by setting it to an empty string.
19+
* Added `GRAALPY_VERSION` and `GRAALPY_VERSION_NUM` C macros.
20+
* Remove `ginstall` module. It hasn't been necessary for several releases. Please, use `pip install`.
21+
* Remove experimental `SetupLLVMLibraryPaths` option. It was used to pre-set library path for LLVM toolchain's libc++. The path can still be set manually.
22+
* Added `GRAALPY_VERSION` and `GRAALPY_VERSION_NUM` C macros
23+
* Added experimental `python.IsolateNativeModules` option to allow loading native extensions multiple times in different contexts. See [the documentation](https://github.com/oracle/graalpython/blob/master/docs/user/Native-Extensions.md) for more information.
24+
* GraalPy Embedding:
25+
* Introduced new types: KeywordArguments and PositionalArguments, in the GraalPy Embedding library (org.graalvm.python:python-embedding), to support directly passing [keyword and positional arguments](https://docs.python.org/3/glossary.html#term-argument) from Java to Python.
26+
* Deprecated the org.graalvm.python.embedding.util API package and added new equivalents to org.graalvm.python.embedding
27+
* Maven and Gradle plugins do not embed Python home into the generated virtual filesystem. Instead, the handling of language home for any Truffle language, including GraalPy, for the GraalVM Native Image build can be controlled by new Native Image options +H:IncludeLanguageResources and +H:CopyLanguageResources. By default, the whole Python home is embedded into the native executable. In the case of JVM deployment, the language home is embedded in the GraalPy artifacts at Mavencentral.
28+
* Removed deprecated methods in VirtualFileSystem
29+
* No longer ship `graalpy_virtualenv` virtualenv plugin within the standard library. Instead, inject the dependency on it into virtualenv, so that it gets installed only when necessary and can be uninstalled.
30+
* Rename `graalpy_virtualenv` to `graalpy_virtualenv_seeder`.
1931

2032
## Version 24.1.0
2133
* GraalPy is now considered stable for pure Python workloads. While many workloads involving native extension modules work, we continue to consider them experimental. You can use the command-line option `--python.WarnExperimentalFeatures` to enable warnings for such modules at runtime. In Java embeddings the warnings are enabled by default and you can suppress them by setting the context option 'python.WarnExperimentalFeatures' to 'false'.

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "overlay": "6cf9b65e57d85fa77c95fa3451bb11ef674bde97" }
1+
{ "overlay": "da4fbb453006eea9997babadc69b70c2e0cee0ab" }

docs/contributor/IMPLEMENTATION_DETAILS.md

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,11 @@ and holding on to the last (if any) in a local variable.
8585
Some PyPI packages contain code that is not compatible with GraalPy.
8686
To overcome this limitation and support such packages, GraalPy contains
8787
patches for some popular packages. The patches are applied to packages
88-
installed via GraalPy specific utility `ginstall` and also to packages
8988
installed via `pip`. This is achieved by patching `pip` code.
9089

9190
The patches are regular POSIX `patch` command compatible diffs located in
92-
`lib-graalpython/patches`. Check out the directory structure and metadate.toml
93-
files to get an idea of how rules are set for patches to be applied.
91+
`lib-graalpython/patches`. The directory has a `README.md` file describing
92+
how the patches are applied.
9493

9594
## The GIL
9695

@@ -259,25 +258,39 @@ until Java GC runs we do not know if they are garbage or not.
259258
* We cannot traverse the managed objects: since we don't do refcounting on the managed
260259
side, we cannot traverse them and decrement refcounts to see if there is a cycle.
261260

262-
The high level solution is that when we see a "dead" cycle going through a managed object
263-
(i.e., cycle not referenced by any native object from the "outside" of the collected set),
261+
The high level solution is that when we see a "dead" cycle going through an object with a managed reference,
262+
(i.e., cycle not referenced by any native object from the "outside" of the collected set,
263+
which may be, however, referenced from managed),
264264
we fully replicate the object graphs (and the cycle) on the managed side (refcounts of native objects
265265
in the cycle, which were not referenced from managed yet, will get new `NativeObjectReference`
266266
created and refcount incremented by `MANAGED_REFCNT`). Managed objects already refer
267267
to the `PythonAbstractNativeObject` wrappers of the native objects (e.g., some Python container
268268
with managed storage), but we also make the native wrappers refer to whatever their referents
269269
are on the Java side (we use `tp_traverse` to find their referents).
270270

271-
Then we make the managed objects in the cycle only weakly referenced on the Java side.
271+
As part of that, we make the objects in the cycle only weakly referenced on the Java side.
272272
One can think about this as pushing the baseline reference count when the
273273
object is eligible for being GC'ed and thus freed. Normally when the object has
274274
`refcount > MANAGED_REFCNT` we keep it alive with a strong reference assuming that
275275
there are some native references to it. In this case, we know that all the native
276276
references to that object are part of potentially dead cycle, and we do not
277277
count them into this limit. Let us call this limit *weak to strong limit*.
278278

279-
After this, if the managed objects are garbage, eventually Java GC will collect them
280-
together with the whole cycle.
279+
After this, if the objects on the managed side (the managed objects or `PythonAbstractNativeObject`
280+
mirrors of native objects) are garbage, eventually Java GC will collect them.
281+
This will push their references to the reference queue. When polled from the queue (`CApiTransitions#pollReferenceQueue`),
282+
we decrement the refcount by `MANAGED_REFCNT` (no managed references anymore) and
283+
if their refcount falls to `0`, they are freed - as part of that, we call the
284+
`tp_clear` slot for native objects, which should call `Py_CLEAR` for their references,
285+
which does `Py_DecRef` - eventually all objects in the cycle should fall to refcount `0`.
286+
287+
*Example: managed object `o1` has refcount `MANAGED_REFCNT+1`: `MANAGED_REFCNT` representing all managed
288+
references, and `+1` for some native object `o2` referencing it. Native object `o2` has
289+
refcount `MANAGED_REFCNT`, because it is referenced only from managed (from `o1`).
290+
Both `o1` and `o2` form a cycle that was already transformed to managed during cycle GC.
291+
The reference queue processing will subtract `MANAGED_REFCNT` from `o1`'s refcount making it `1`.
292+
Then the reference queue processing will subtract `MANAGED_REFCNT` from `o2`'s refcount making it fall
293+
to `0` - this triggers the `tp_clear` of `o2`, which should subtract the final `1` from `o1`'s refcount.*
281294

282295
If some of the managed objects are not garbage, and they passed back to native code,
283296
the native code can then access and resurrect the whole cycle. W.r.t. the refcounts
@@ -289,3 +302,19 @@ checking the same `MANAGED_REFCNT` limit for all objects, the subsequent `Py_Dec
289302
call for this object will not detect that the reference should be made weak again!
290303
However, this is OK, it only prolongs the collection: we will make it weak again in
291304
the next run of the cycle GC on the native side.
305+
306+
## C extension copying
307+
308+
On Linux, Python native extensions expect to lookup Python C API functions in the global namespace and specify no explicit dependency on any libpython.
309+
To isolate them, we copy them with a new name, change their `SONAME`, add a `DT_NEEDED` dependency on a copy of our libpython shared object, and finally load them with `RTLD_LOCAL`.
310+
The ELF format is not really meant to allow such modifications after the fact.
311+
The most widely used tool to do so, [patchelf](https://github.com/NixOS/patchelf), still sees regular bugfixes and can corrupt ELF files.
312+
313+
On Windows there is no global namespace so native extensions already have a dependency on our libpython DLL.
314+
We copy them and just change the dependency to point to the context-local copy of libpython rather than the global one.
315+
316+
On macOS, while two-level namespaces exist, Python extensions historically use `-undefined dynamic_lookup` where they (just like in Linux) expect to find C API functions in any loaded image.
317+
We have to apply a similar workaround as on Linux, copy to a new name, change the `LC_ID_DYLIB` to that name, and add a `LC_LOAD_DYLIB` section to make the linker load the symbols from our libpython.
318+
This is currently not fully implemented.
319+
320+
Note that any code signatures are invalidated by this process.

0 commit comments

Comments
 (0)