diff --git a/ci.jsonnet b/ci.jsonnet index 22a08ec2fc..a6a799a484 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -241,6 +241,7 @@ logs+: [ "default.iprof.gz", "default.lcov", + "host-inlining.txt.gz", ], }), }), diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TRegexUtil.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TRegexUtil.java index cdd0441fdc..34edb85a36 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TRegexUtil.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TRegexUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, 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 @@ -91,8 +91,8 @@ private RegexResult() { private static final String NUMBER_OF_REGEX_RESULT_TYPES = "1"; - @GenerateCached - @GenerateInline(inlineByDefault = true) + @GenerateCached(false) + @GenerateInline @GenerateUncached public abstract static class InteropReadMemberNode extends Node { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIOMixinBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIOMixinBuiltins.java index 5d8a1f3cbc..eb89c28eb9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIOMixinBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIOMixinBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, 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 @@ -275,7 +275,7 @@ static long doit(VirtualFrame frame, PBuffered self, Object off, int whence, @Cached("create(T_SEEK)") CheckIsClosedNode checkIsClosedNode, @Cached BufferedIONodes.CheckIsSeekabledNode checkIsSeekabledNode, @Cached BufferedIONodes.AsOffNumberNode asOffNumberNode, - @Cached(inline = true) BufferedIONodes.SeekNode seekNode) { + @Cached BufferedIONodes.SeekNode seekNode) { checkIsClosedNode.execute(frame, self); checkIsSeekabledNode.execute(frame, self); long pos = asOffNumberNode.execute(frame, inliningTarget, off, TypeError); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIONodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIONodes.java index f6de4820a8..a1835cbe60 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIONodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIONodes.java @@ -245,7 +245,7 @@ RawTellNode doIt(@Cached(inline = false) RawTellNode node) { } } - @GenerateInline(inlineByDefault = true) + @GenerateInline @GenerateCached(false) abstract static class RawTellIgnoreErrorNode extends PNodeWithContext { public abstract long execute(VirtualFrame frame, Node inliningTarget, PBuffered self); @@ -337,7 +337,7 @@ protected static void readWrite(VirtualFrame frame, PBuffered self, * implementation of cpython/Modules/_io/bufferedio.c:_io__Buffered_seek_impl */ @GenerateInline - @GenerateCached + @GenerateCached(false) abstract static class SeekNode extends PNodeWithContext { public abstract long execute(VirtualFrame frame, Node inliningTarget, PBuffered self, long off, int whence); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java index 655b4cfa27..1015ab3357 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java @@ -535,8 +535,8 @@ static PComplex runGeneric(Node inliningTarget, Object value, * avoid eager and explicit conversion. */ @ImportStatic(PythonUtils.class) - @GenerateInline(inlineByDefault = true) - @GenerateCached + @GenerateInline + @GenerateCached(false) @GenerateUncached public abstract static class CastToNativeLongNode extends PNodeWithContext { public abstract long execute(Node inliningTarget, boolean arg); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java index d0d730189b..4e99840aa5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java @@ -229,7 +229,6 @@ import com.oracle.truffle.api.dsl.GenerateInline; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.ImportStatic; -import com.oracle.truffle.api.dsl.NeverDefault; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.DenyReplace; import com.oracle.truffle.api.nodes.Node; @@ -1991,8 +1990,8 @@ private static TpSlots initializeNativeSlots(PythonAbstractNativeObject nativeKl } } - @GenerateInline(inlineByDefault = true) - @GenerateCached + @GenerateInline + @GenerateCached(false) @ImportStatic(PGuards.class) public abstract static class GetCachedTpSlotsNode extends Node { public abstract TpSlots execute(Node inliningTarget, Object pythonClass); @@ -2025,25 +2024,16 @@ public static GetCachedTpSlotsNode getUncached() { } } - @GenerateInline(inlineByDefault = true) - @GenerateCached + @GenerateInline + @GenerateCached(false) @GenerateUncached public abstract static class GetObjectSlotsNode extends Node { public abstract TpSlots execute(Node inliningTarget, Object pythonObject); - public final TpSlots executeCached(Object pythonObject) { - return execute(this, pythonObject); - } - public static TpSlots executeUncached(Object pythonObject) { return GetObjectSlotsNodeGen.getUncached().execute(null, pythonObject); } - @NeverDefault - public static GetObjectSlotsNode create() { - return GetObjectSlotsNodeGen.create(); - } - // Note: it seems that switching the GetClassNode with an adhoc GetClassNode variant that // does not have any inline caches does not change peak at least for micro:if-polymorph // TODO: verify this on all benchmarks and get rid of the IC if possible diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyEnterRecursiveCallNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyEnterRecursiveCallNode.java index b8afef2b71..adda9f8a03 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyEnterRecursiveCallNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyEnterRecursiveCallNode.java @@ -62,7 +62,7 @@ * and {@code _Py_EnterRecursiveCall}. */ @GenerateUncached -@GenerateInline(inlineByDefault = true) +@GenerateInline @GenerateCached(false) public abstract class PyEnterRecursiveCallNode extends PNodeWithContext { protected abstract PythonThreadState execute(Node inliningTarget, TruffleString errorMessage, Object formatArg, boolean withFormatArg); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyLongAsLongAndOverflowNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyLongAsLongAndOverflowNode.java index 49ee94f203..e9450f292e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyLongAsLongAndOverflowNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyLongAsLongAndOverflowNode.java @@ -61,7 +61,7 @@ * {@link com.oracle.graal.python.util.OverflowException}. */ @GenerateUncached -@GenerateInline(inlineByDefault = true) +@GenerateInline @GenerateCached(false) public abstract class PyLongAsLongAndOverflowNode extends PNodeWithContext { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/GetFixedAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/GetFixedAttributeNode.java index c7d4265fe6..4f06d56c5d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/GetFixedAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/GetFixedAttributeNode.java @@ -66,7 +66,7 @@ Object doIt(VirtualFrame frame, Object object, @Bind Node inliningTarget, @Cached GetClassNode getClassNode, @Cached GetCachedTpSlotsNode getSlotsNode, - @Cached(inline = true) MergedObjectTypeModuleGetFixedAttributeNode innerNode) { + @Cached MergedObjectTypeModuleGetFixedAttributeNode innerNode) { Object type = getClassNode.execute(inliningTarget, object); TpSlots slots = getSlotsNode.execute(inliningTarget, type); return innerNode.execute(frame, inliningTarget, object, key, type, slots); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/MergedObjectTypeModuleGetFixedAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/MergedObjectTypeModuleGetFixedAttributeNode.java index d74a71d49c..33ec150b59 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/MergedObjectTypeModuleGetFixedAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/MergedObjectTypeModuleGetFixedAttributeNode.java @@ -82,7 +82,7 @@ * inlining, but the caller is expected to keep its identity stable for the lifetime of the node. */ @GenerateInline -@GenerateCached +@GenerateCached(false) public abstract class MergedObjectTypeModuleGetFixedAttributeNode extends PNodeWithContext { public abstract Object execute(VirtualFrame frame, Node inliningTarget, Object object, TruffleString key, Object type, TpSlots slots); diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py index 8392bc9d86..d56b2022d2 100644 --- a/mx.graalpython/mx_graalpython.py +++ b/mx.graalpython/mx_graalpython.py @@ -411,6 +411,13 @@ def graalpy_native_pgo_build_and_test(args=None): if mx_sdk_vm_ng.get_bootstrap_graalvm_version() < mx.VersionSpec("25.0"): mx.abort("python-native-pgo not supported on GraalVM < 25") + host_inlining_log = Path(SUITE.dir) / "host-inlining.txt" + host_inlining_log_gz = Path(str(host_inlining_log) + ".gz") + if host_inlining_log.exists(): + host_inlining_log.unlink() + if host_inlining_log_gz.exists(): + host_inlining_log_gz.unlink() + with set_env(GRAALPY_PGO_PROFILE=""): mx.log(mx.colorize("[PGO] Building PGO-instrumented native image", color="yellow")) build_home = graalpy_standalone_home('native', enterprise=True, build=True) @@ -469,11 +476,19 @@ def graalpy_native_pgo_build_and_test(args=None): if not os.path.isfile(iprof_path): mx.abort(f"[PGO] Could not find profile file at expected location: {iprof_path}") - with set_env(GRAALPY_PGO_PROFILE=str(iprof_path)): + with set_env(GRAALPY_PGO_PROFILE=str(iprof_path), GRAALPY_HOST_INLINING_LOG=str(host_inlining_log)): mx.log(mx.colorize("[PGO] Building optimized native image with collected profile", color="yellow")) native_bin = graalpy_standalone('native', enterprise=True, build=True) mx.log(mx.colorize(f"[PGO] Optimized PGO build complete: {native_bin}", color="yellow")) + if host_inlining_log.exists(): + mx.log(mx.colorize(f"[PGO] Host inlining log at: {host_inlining_log}", color="yellow")) + with open(host_inlining_log, 'rb') as f_in, gzip.open(host_inlining_log_gz, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + host_inlining_log.unlink() + mx.log(mx.colorize(f"[PGO] Gzipped host inlining log at: {host_inlining_log_gz}", color="yellow")) + else: + mx.warn(f"[PGO] Host inlining log was not produced at expected location: {host_inlining_log}") iprof_gz_path = str(iprof_path) + '.gz' with open(iprof_path, 'rb') as f_in, gzip.open(iprof_gz_path, 'wb') as f_out: @@ -948,6 +963,14 @@ def graalpy_standalone_home(standalone_type, enterprise=False, dev=False, build= mx_args.append(f"--extra-image-builder-argument=--pgo={pgo_profile}") mx_args.append(f"--extra-image-builder-argument=-H:+UnlockExperimentalVMOptions") mx_args.append(f"--extra-image-builder-argument=-H:+PGOPrintProfileQuality") + if host_inlining_log := os.environ.get("GRAALPY_HOST_INLINING_LOG"): + mx_args.extend([ + f"--extra-image-builder-argument=-H:Log=HostInliningPhase,~CanonicalizerPhase,~GraphBuilderPhase", + f"--extra-image-builder-argument=-H:+TruffleHostInliningPrintExplored", + f"--extra-image-builder-argument=-H:MethodFilter=com.oracle.graal.python.*.*", + f"--extra-image-builder-argument=-H:-UnlockExperimentalVMOptions", + f"--extra-image-builder-argument=-Dgraal.LogFile={host_inlining_log}", + ]) else: mx_args.append(f"--extra-image-builder-argument=--pgo-instrument") mx_args.append(f"--extra-image-builder-argument=-H:+UnlockExperimentalVMOptions")