From d159d1d217b6f767c0079250bc245432d615064e Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 13:45:21 +0200 Subject: [PATCH 01/26] Add shared root-backed executable infrastructure --- .../oracle/graal/python/PythonLanguage.java | 119 +++++++++++++++- .../python/builtins/objects/code/PCode.java | 103 ++++++++++++-- .../objects/function/PBuiltinFunction.java | 128 ++++++++++++++++-- .../builtins/objects/function/PFunction.java | 12 +- .../graal/python/runtime/object/PFactory.java | 64 ++++++++- 5 files changed, 395 insertions(+), 31 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 9fc3341abe..01c9739697 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -319,13 +319,23 @@ public boolean isSingleContext() { * {@link java.util.concurrent.ConcurrentHashMap.Node} objects into the image heap. */ private final EconomicMap imageBuildtimeCachedCallTargets = ImageInfo.inImageCode() ? EconomicMap.create() : null; + /** + * Root nodes that are populated during native-image build time and then only read at image + * runtime. + */ + private final EconomicMap imageBuildtimeCachedRootNodes = ImageInfo.inImageCode() ? EconomicMap.create() : null; /** * Call targets added after image startup, or all cached call targets when running on the JVM. */ private final ConcurrentHashMap runtimeCachedCallTargets = new ConcurrentHashMap<>(); + /** + * Root nodes added after image startup, or all cached root nodes when running on the JVM. + */ + private final ConcurrentHashMap runtimeCachedRootNodes = new ConcurrentHashMap<>(); @CompilationFinal(dimensions = 1) private final RootCallTarget[] builtinSlotsCallTargets; @CompilationFinal(dimensions = 1) private RootCallTarget[] capiCallTargets; + @CompilationFinal(dimensions = 1) private final RootNode[] builtinSlotsRootNodes; /** * We cannot initialize call targets in language ctor and the next suitable hook is context @@ -389,6 +399,7 @@ public PythonLanguage() { throw new IllegalStateException("Slots must be initialized in PythonBuiltinClassType static initializer"); } builtinSlotsCallTargets = new RootCallTarget[TpSlot.getBuiltinsCallTargetsCount()]; + builtinSlotsRootNodes = new RootNode[TpSlot.getBuiltinsCallTargetsCount()]; } /** @@ -1068,12 +1079,27 @@ private Shape createBuiltinShape(PythonBuiltinClassType type, int ordinal) { } public RootCallTarget getBuiltinSlotCallTarget(int index) { - return builtinSlotsCallTargets[index]; + RootCallTarget callTarget = builtinSlotsCallTargets[index]; + if (callTarget == null) { + RootNode rootNode = builtinSlotsRootNodes[index]; + if (rootNode != null) { + callTarget = rootNode.getCallTarget(); + VarHandle.storeStoreFence(); + builtinSlotsCallTargets[index] = callTarget; + } + } + return callTarget; } public void setBuiltinSlotCallTarget(int index, RootCallTarget callTarget) { VarHandle.storeStoreFence(); builtinSlotsCallTargets[index] = callTarget; + builtinSlotsRootNodes[index] = callTarget != null ? callTarget.getRootNode() : null; + } + + public void setBuiltinSlotRootNode(int index, RootNode rootNode) { + VarHandle.storeStoreFence(); + builtinSlotsRootNodes[index] = rootNode; } public RootCallTarget getCapiCallTarget(int index) { @@ -1107,6 +1133,12 @@ public RootCallTarget createCachedCallTarget(Function return createCachedCallTargetUnsafe(rootNodeFunction, key, true); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class key) { + assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length <= 1; + assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length == 0 || key.getConstructors()[0].getParameterCount() == 0; + return createCachedRootNodeUnsafe(rootNodeFunction, key, true); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Enum key) { return createCachedCallTargetUnsafe(rootNodeFunction, key, true); } @@ -1115,6 +1147,10 @@ public RootCallTarget createCachedCallTarget(Function return createCachedCallTargetUnsafe(rootNodeFunction, key, true); } + public RootNode createCachedRootNode(Function rootNodeFunction, Enum key) { + return createCachedRootNodeUnsafe(rootNodeFunction, key, true); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, String key) { // for builtins: name is needed to distinguish builtins that share the same underlying node // in general: a String may be parameter of the node wrapped in the root node or the root @@ -1123,36 +1159,66 @@ public RootCallTarget createCachedCallTarget(Function return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, String key) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); + } + // Variant that should be called at most once per context, because it does not cache the target // in single context mode public RootCallTarget initBuiltinCallTarget(Function rootNodeFunction, Class nodeClass, String key) { return createCachedCallTargetUnsafe(rootNodeFunction, false, nodeClass, key); } + // Variant that should be called at most once per context, because it does not cache the root + // node in single context mode + public RootNode initBuiltinRootNode(Function rootNodeFunction, Class nodeClass, String key) { + return createCachedRootNodeUnsafe(rootNodeFunction, false, nodeClass, key); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, TruffleString key) { // See the String overload return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, TruffleString key) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, int key) { return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, int key) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { // for slot call targets and wrappers: the root node may be wrapping a helper wrapper node // implementing the slot wrapper logic and the bare slot node itself return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, name); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, name); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { // for slot wrappers: the type is used for validation of "self" type return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name); } + public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, CodeUnit key) { return createCachedCallTargetUnsafe(rootNodeFunction, true, key); } + public RootNode createCachedRootNode(Function rootNodeFunction, CodeUnit key) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, key); + } + /** * Caches call targets for external C functions created by extensions at runtime. *

@@ -1166,6 +1232,12 @@ public RootCallTarget createCachedExternalFunWrapperCallTarget(Function rootNodeFunction, + Class klass, Enum signature, TruffleString name, + boolean doArgumentAndResultConversion, boolean isStatic) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, klass, signature, name, doArgumentAndResultConversion, isStatic); + } + public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Enum signature, TruffleString name, boolean doArgumentAndResultConversion) { return createCachedCallTargetUnsafe(rootNodeFunction, true, signature, name, doArgumentAndResultConversion); @@ -1175,13 +1247,19 @@ public RootCallTarget createCachedCallTarget(Function return createCachedCallTargetUnsafe(rootNodeFunction, true, signature, name); } + public RootNode createStructSeqIndexedMemberAccessCachedRootNode(Function rootNodeFunction, int memberIndex) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, StructSequence.class, memberIndex); + } + public RootCallTarget createStructSeqIndexedMemberAccessCachedCallTarget(Function rootNodeFunction, int memberIndex) { return createCachedCallTargetUnsafe(rootNodeFunction, true, StructSequence.class, memberIndex); } + public RootNode createCachedPropAccessRootNode(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { + return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, name, type, offset); + } + public RootCallTarget createCachedPropAccessCallTarget(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { - // For the time being, we assume finite/limited number of cext/hpy types members, their - // types and offsets return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, name, type, offset); } @@ -1204,10 +1282,23 @@ private RootCallTarget createCachedCallTargetUnsafe(Function rootNodeFunction, Object key, boolean cacheInSingleContext) { + CompilerAsserts.neverPartOfCompilation(); + if (cacheInSingleContext || !singleContext) { + return getOrCreateCachedRootNode(rootNodeFunction, key); + } else { + return rootNodeFunction.apply(this); + } + } + private RootCallTarget createCachedCallTargetUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { return createCachedCallTargetUnsafe(rootNodeFunction, Arrays.asList(cacheKeys), cacheInSingleContext); } + private RootNode createCachedRootNodeUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { + return createCachedRootNodeUnsafe(rootNodeFunction, Arrays.asList(cacheKeys), cacheInSingleContext); + } + private RootCallTarget getOrCreateCachedCallTarget(Function rootNodeFunction, Object key) { CompilerAsserts.neverPartOfCompilation(); if (ImageInfo.inImageRuntimeCode()) { @@ -1230,6 +1321,28 @@ private RootCallTarget getOrCreateCachedCallTarget(Function PythonUtils.getOrCreateCallTarget(rootNodeFunction.apply(this))); } + private RootNode getOrCreateCachedRootNode(Function rootNodeFunction, Object key) { + CompilerAsserts.neverPartOfCompilation(); + if (ImageInfo.inImageRuntimeCode()) { + RootNode preinitialized = imageBuildtimeCachedRootNodes.get(key); + if (preinitialized != null) { + return preinitialized; + } + return runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); + } + if (ImageInfo.inImageBuildtimeCode()) { + synchronized (imageBuildtimeCachedRootNodes) { + RootNode cached = imageBuildtimeCachedRootNodes.get(key); + if (cached == null) { + cached = rootNodeFunction.apply(this); + imageBuildtimeCachedRootNodes.put(key, cached); + } + return cached; + } + } + return runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); + } + @Override protected void exitContext(PythonContext context, ExitMode exitMode, int exitCode) { if (context.getCApiContext() != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 1f10629bb3..15feae7b7d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -46,6 +46,7 @@ import java.math.BigInteger; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.bytes.PBytes; @@ -87,6 +88,9 @@ @ExportLibrary(InteropLibrary.class) public final class PCode extends PythonBuiltinObject { + private static final AtomicInteger TRACKED_CODE_COUNT = new AtomicInteger(); + private static final AtomicInteger TRACKED_CODE_CALL_TARGET_COUNT = new AtomicInteger(); + public static final int CO_OPTIMIZED = 0x1; public static final int CO_NEWLOCALS = 0x2; public static final int CO_VARARGS = 0x4; @@ -100,8 +104,11 @@ public final class PCode extends PythonBuiltinObject { /* GraalPy-specific */ public static final int CO_GRAALPYHON_MODULE = 0x1000; - private final RootCallTarget callTarget; + private final RootNode rootNode; + private volatile RootCallTarget callTarget; private final Signature signature; + private final boolean trackCallTargetInitialization; + private volatile boolean callTargetCounted; // number of local variables private int nlocals = -1; @@ -141,8 +148,11 @@ public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget) { public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, TruffleString filename) { super(cls, instanceShape); + this.rootNode = callTarget.getRootNode(); this.callTarget = callTarget; this.signature = Signature.fromCallTarget(callTarget); + this.trackCallTargetInitialization = false; + this.callTargetCounted = true; this.filename = filename; } @@ -185,8 +195,65 @@ public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signatu this.linetable = linetable; this.freevars = freevars; this.cellvars = cellvars; + this.rootNode = callTarget.getRootNode(); this.callTarget = callTarget; this.signature = signature; + this.trackCallTargetInitialization = false; + this.callTargetCounted = true; + assert signature != null; + } + + public PCode(Object cls, Shape instanceShape, PRootNode rootNode, TruffleString filename) { + super(cls, instanceShape); + this.rootNode = rootNode; + this.signature = rootNode.getSignature(); + this.trackCallTargetInitialization = true; + this.filename = filename; + TRACKED_CODE_COUNT.incrementAndGet(); + } + + public PCode(Object cls, Shape instanceShape, PRootNode rootNode, int flags, int firstlineno, byte[] linetable, TruffleString filename) { + this(cls, instanceShape, rootNode, filename); + this.flags = flags; + this.firstlineno = firstlineno; + this.linetable = linetable; + } + + public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { + this(cls, instanceShape, rootNode, signature, codeUnit.varnames.length, -1, -1, null, null, + null, null, null, filename, + codeUnit.name, codeUnit.qualname, -1, codeUnit.srcOffsetTable); + } + + public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { + this(cls, instanceShape, rootNode, signature, codeUnit.varnames.length, -1, -1, null, null, + null, null, null, filename, + codeUnit.name, codeUnit.qualname, -1, null); + } + + public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, int nlocals, + int stacksize, int flags, Object[] constants, TruffleString[] names, + TruffleString[] varnames, TruffleString[] freevars, TruffleString[] cellvars, + TruffleString filename, TruffleString name, TruffleString qualname, + int firstlineno, byte[] linetable) { + super(cls, instanceShape); + this.nlocals = nlocals; + this.stacksize = stacksize; + this.flags = flags; + this.constants = constants; + this.names = names; + this.varnames = varnames; + this.filename = filename; + this.name = name; + this.qualname = qualname; + this.firstlineno = firstlineno; + this.linetable = linetable; + this.freevars = freevars; + this.cellvars = cellvars; + this.rootNode = rootNode; + this.signature = signature; + this.trackCallTargetInitialization = true; + TRACKED_CODE_COUNT.incrementAndGet(); assert signature != null; } @@ -347,7 +414,7 @@ private static CodeUnit getCodeUnit(RootNode node) { } RootNode getRootNode() { - return getRootCallTarget().getRootNode(); + return rootNode; } RootNode getRootNodeForExtraction() { @@ -505,9 +572,8 @@ public PCode getOrCreateChildCode(int index, BytecodeDSLCodeUnit codeUnit) { private PCode createCode(BytecodeDSLCodeUnit codeUnit) { PBytecodeDSLRootNode outerRootNode = (PBytecodeDSLRootNode) getRootNodeForExtraction(); PythonLanguage language = outerRootNode.getLanguage(); - RootCallTarget callTarget = language.createCachedCallTarget(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); - PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) callTarget.getRootNode(); - return PFactory.createCode(language, callTarget, rootNode.getSignature(), codeUnit, getFilename()); + PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); + return PFactory.createCode(language, rootNode, rootNode.getSignature(), codeUnit, getFilename()); } public PCode getOrCreateChildCode(int index, BytecodeCodeUnit codeUnit) { @@ -524,13 +590,13 @@ public PCode getOrCreateChildCode(int index, BytecodeCodeUnit codeUnit) { private PCode createCode(BytecodeCodeUnit codeUnit) { PBytecodeRootNode outerRootNode = (PBytecodeRootNode) getRootNodeForExtraction(); PythonLanguage language = outerRootNode.getLanguage(); - RootCallTarget callTarget = language.createCachedCallTarget( + PRootNode executableRootNode = (PRootNode) language.createCachedRootNode( l -> PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getSource(), outerRootNode.isInternal()), codeUnit); - RootNode rootNode = callTarget.getRootNode(); - if (rootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { + RootNode rootNode = executableRootNode; + if (executableRootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { rootNode = generatorRoot.getBytecodeRootNode(); } - return PFactory.createCode(language, callTarget, ((PBytecodeRootNode) rootNode).getSignature(), codeUnit, getFilename()); + return PFactory.createCode(language, executableRootNode, ((PBytecodeRootNode) rootNode).getSignature(), codeUnit, getFilename()); } @TruffleBoundary @@ -611,7 +677,24 @@ public Signature getSignature() { } public RootCallTarget getRootCallTarget() { - return callTarget; + RootCallTarget ct = callTarget; + if (ct == null) { + ct = rootNode.getCallTarget(); + callTarget = ct; + if (trackCallTargetInitialization && !callTargetCounted) { + callTargetCounted = true; + TRACKED_CODE_CALL_TARGET_COUNT.incrementAndGet(); + } + } + return ct; + } + + public static int getTrackedCodeCount() { + return TRACKED_CODE_COUNT.get(); + } + + public static int getTrackedCodeCallTargetCount() { + return TRACKED_CODE_CALL_TARGET_COUNT.get(); } @ExportMessage diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index 972dee05cb..96b3f2f15a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -29,6 +29,7 @@ import static com.oracle.graal.python.nodes.StringLiterals.T_DOT; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.Builtin; @@ -71,11 +72,71 @@ */ @ExportLibrary(InteropLibrary.class) public final class PBuiltinFunction extends PythonBuiltinObject implements BoundBuiltinCallable { + private static final AtomicInteger TRACKED_BUILTIN_FUNCTION_COUNT = new AtomicInteger(); + private static final AtomicInteger TRACKED_BUILTIN_CALL_TARGET_COUNT = new AtomicInteger(); + + private static final class Executable { + private final RootNode functionRootNode; + private final Signature signature; + private final boolean trackCallTargetInitialization; + private volatile RootCallTarget callTarget; + private volatile boolean callTargetCounted; + + private Executable(RootCallTarget callTarget, boolean trackCallTargetInitialization) { + this.functionRootNode = callTarget.getRootNode(); + this.signature = ((PRootNode) functionRootNode).getSignature(); + this.callTarget = callTarget; + this.trackCallTargetInitialization = trackCallTargetInitialization; + this.callTargetCounted = callTarget != null; + if (trackCallTargetInitialization) { + TRACKED_BUILTIN_FUNCTION_COUNT.incrementAndGet(); + TRACKED_BUILTIN_CALL_TARGET_COUNT.incrementAndGet(); + } + } + + private Executable(PRootNode rootNode, boolean trackCallTargetInitialization) { + this.functionRootNode = rootNode; + this.signature = rootNode.getSignature(); + this.trackCallTargetInitialization = trackCallTargetInitialization; + if (trackCallTargetInitialization) { + TRACKED_BUILTIN_FUNCTION_COUNT.incrementAndGet(); + } + } + + private synchronized RootCallTarget getCallTarget() { + RootCallTarget ct = callTarget; + if (ct == null) { + ct = functionRootNode.getCallTarget(); + callTarget = ct; + if (trackCallTargetInitialization && !callTargetCounted) { + callTargetCounted = true; + TRACKED_BUILTIN_CALL_TARGET_COUNT.incrementAndGet(); + } + } + return ct; + } + + private RootNode getFunctionRootNode() { + return functionRootNode; + } + + private NodeFactory getBuiltinNodeFactory() { + return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot ? builtinRoot.getFactory() : null; + } + + private boolean declaresExplicitSelf() { + return !(functionRootNode instanceof BuiltinFunctionRootNode builtinRoot) || builtinRoot.declaresExplicitSelf(); + } + + private boolean forceSplitDirectCalls() { + return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot && builtinRoot.getBuiltin().forceSplitDirectCalls(); + } + } private final PString name; private final TruffleString qualname; private final Object enclosingType; - private final RootCallTarget callTarget; + private final Executable executable; private final Signature signature; private final int flags; private final TpSlot slot; @@ -83,7 +144,7 @@ public final class PBuiltinFunction extends PythonBuiltinObject implements Bound @CompilationFinal(dimensions = 1) private final Object[] defaults; @CompilationFinal(dimensions = 1) private final PKeyword[] kwDefaults; - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, + private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, Executable executable, TpSlot slot, PExternalFunctionWrapper slotWrapper) { super(cls, shape); this.name = PythonUtils.toPString(name); @@ -93,8 +154,8 @@ public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString n this.qualname = name; } this.enclosingType = enclosingType; - this.callTarget = callTarget; - this.signature = ((PRootNode) callTarget.getRootNode()).getSignature(); + this.executable = executable; + this.signature = executable.signature; this.flags = flags; this.defaults = defaults; this.kwDefaults = kwDefaults != null ? kwDefaults : generateKwDefaults(signature); @@ -102,10 +163,40 @@ public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString n this.slotWrapper = slotWrapper; } + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, + TpSlot slot, PExternalFunctionWrapper slotWrapper) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget, false), slot, slotWrapper); + } + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget) { this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, callTarget, null, null); } + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, + boolean trackCallTargetInitialization) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget, trackCallTargetInitialization), null, null); + } + + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, + PRootNode rootNode, boolean trackCallTargetInitialization) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, trackCallTargetInitialization), null, null); + } + + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, + PRootNode rootNode) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, false), null, null); + } + + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, + PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, false), slot, slotWrapper); + } + + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PBuiltinFunction source, + TpSlot slot, PExternalFunctionWrapper slotWrapper) { + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, source.executable, slot, slotWrapper); + } + public static PKeyword[] generateKwDefaults(Signature signature) { TruffleString[] keywordNames = signature.getKeywordNames(); PKeyword[] kwDefaults = PKeyword.create(keywordNames.length); @@ -129,7 +220,7 @@ public static Object[] generateDefaults(int numDefaults) { } public RootNode getFunctionRootNode() { - return callTarget.getRootNode(); + return executable.getFunctionRootNode(); } /** @@ -149,12 +240,7 @@ public PExternalFunctionWrapper getSlotWrapper() { } public NodeFactory getBuiltinNodeFactory() { - RootNode functionRootNode = getFunctionRootNode(); - if (functionRootNode instanceof BuiltinFunctionRootNode builtinRoot) { - return builtinRoot.getFactory(); - } else { - return null; - } + return executable.getBuiltinNodeFactory(); } public int getFlags() { @@ -211,7 +297,23 @@ public Signature getSignature() { } public RootCallTarget getCallTarget() { - return callTarget; + return executable.getCallTarget(); + } + + public boolean declaresExplicitSelf() { + return executable.declaresExplicitSelf(); + } + + public boolean forceSplitDirectCalls() { + return executable.forceSplitDirectCalls(); + } + + public static int getTrackedBuiltinFunctionCount() { + return TRACKED_BUILTIN_FUNCTION_COUNT.get(); + } + + public static int getTrackedBuiltinCallTargetCount() { + return TRACKED_BUILTIN_CALL_TARGET_COUNT.get(); } public TruffleString getName() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java index 5bd0acfece..c47348da59 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -90,7 +90,6 @@ public PFunction(PythonLanguage lang, TruffleString name, TruffleString qualname this.qualname = qualname; assert code != null; this.code = this.finalCode = code; - this.callTarget = code.getRootCallTarget(); this.globals = globals; this.defaultValues = this.finalDefaultValues = defaultValues == null ? PythonUtils.EMPTY_OBJECT_ARRAY : defaultValues; this.kwDefaultValues = this.finalKwDefaultValues = kwDefaultValues == null ? PKeyword.EMPTY_KEYWORDS : kwDefaultValues; @@ -171,7 +170,12 @@ public PCode getCode() { } public RootCallTarget getCallTarget() { - return callTarget; + RootCallTarget ct = callTarget; + if (ct == null) { + ct = getCode().getRootCallTarget(); + callTarget = ct; + } + return ct; } @TruffleBoundary @@ -180,7 +184,7 @@ public void setCode(PCode code) { assert code != null : "code cannot be null"; this.finalCode = null; this.code = code; - this.callTarget = code.getRootCallTarget(); + this.callTarget = null; } public Object[] getDefaults() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index d778a74756..63fd97857f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -233,6 +233,7 @@ import com.oracle.graal.python.builtins.objects.typing.PTypeVar; import com.oracle.graal.python.builtins.objects.typing.PTypeVarTuple; import com.oracle.graal.python.compiler.BytecodeCodeUnit; +import com.oracle.graal.python.nodes.PRootNode; import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode; import com.oracle.graal.python.nodes.bytecode_dsl.BytecodeDSLCodeUnit; import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode; @@ -519,10 +520,26 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Tr PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget); } + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, RootCallTarget callTarget, + boolean trackCallTargetInitialization) { + return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, + PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget, trackCallTargetInitialization); + } + + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode, + boolean trackCallTargetInitialization) { + return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, + PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, trackCallTargetInitialization); + } + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, RootCallTarget callTarget) { return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, callTarget); } + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, PRootNode rootNode) { + return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, rootNode); + } + public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, RootCallTarget callTarget, TpSlot slot, PExternalFunctionWrapper slotWrapper) { return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, @@ -535,16 +552,34 @@ public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, callTarget, slot, slotWrapper); } + public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode, TpSlot slot, + PExternalFunctionWrapper slotWrapper) { + return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, + PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, slot, slotWrapper); + } + + public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, PRootNode rootNode, + TpSlot slot, PExternalFunctionWrapper slotWrapper) { + return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, defaults, kw, flags, + rootNode, slot, slotWrapper); + } + public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object type, Object[] defaults, PKeyword[] kwdefaults, RootCallTarget callTarget, TpSlot slot) { PBuiltinFunction func = createWrapperDescriptor(language, T___NEW__, type, defaults, kwdefaults, CExtContext.METH_VARARGS | CExtContext.METH_KEYWORDS, callTarget, slot, PExternalFunctionWrapper.NEW); return createBuiltinMethod(language, type, func); } + public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object type, Object[] defaults, PKeyword[] kwdefaults, PRootNode rootNode, TpSlot slot) { + PBuiltinFunction func = createWrapperDescriptor(language, T___NEW__, type, defaults, kwdefaults, CExtContext.METH_VARARGS | CExtContext.METH_KEYWORDS, rootNode, slot, + PExternalFunctionWrapper.NEW); + return createBuiltinMethod(language, type, func); + } + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, PBuiltinFunction function, Object klass) { PythonBuiltinClassType type = (PythonBuiltinClassType) function.getPythonClass(); return new PBuiltinFunction(type, type.getInstanceShape(language), function.getName(), klass, - function.getDefaults(), function.getKwDefaults(), function.getFlags(), function.getCallTarget(), + function.getDefaults(), function.getKwDefaults(), function.getFlags(), function, function.getSlot(), function.getSlotWrapper()); } @@ -1080,18 +1115,34 @@ public static PCode createCode(PythonLanguage language, RootCallTarget ct, Truff return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, filename); } + public static PCode createCode(PythonLanguage language, PRootNode rootNode, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, filename); + } + public static PCode createCode(PythonLanguage language, RootCallTarget ct, int flags, int firstlineno, byte[] linetable, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, flags, firstlineno, linetable, filename); } + public static PCode createCode(PythonLanguage language, PRootNode rootNode, int flags, int firstlineno, byte[] linetable, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, flags, firstlineno, linetable, filename); + } + public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, codeUnit, filename); } + public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); + } + public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, codeUnit, filename); } + public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); + } + public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, int nlocals, int stacksize, int flags, Object[] constants, TruffleString[] names, TruffleString[] varnames, @@ -1103,6 +1154,17 @@ public static PCode createCode(PythonLanguage language, RootCallTarget callTarge filename, name, qualname, firstlineno, linetable); } + public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, int nlocals, + int stacksize, int flags, Object[] constants, + TruffleString[] names, TruffleString[] varnames, + TruffleString[] freevars, TruffleString[] cellvars, + TruffleString filename, TruffleString name, TruffleString qualname, + int firstlineno, byte[] linetable) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, + nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, + filename, name, qualname, firstlineno, linetable); + } + /* * Socket */ From 6c7f5ce59f5c76ab536b5b72dbce5a0ae692697a Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 14:13:51 +0200 Subject: [PATCH 02/26] Convert builtin callables to shared roots --- .../graal/python/builtins/PythonBuiltins.java | 11 ++++---- .../cext/capi/CApiMemberAccessNodes.java | 25 +++++++++---------- .../objects/tuple/StructSequence.java | 7 +++--- .../builtins/objects/type/TypeNodes.java | 15 ++++++++--- .../python/nodes/call/CallDispatchers.java | 6 ++--- .../call/special/AbstractCallMethodNode.java | 7 +----- .../oracle/graal/python/util/PythonUtils.java | 16 ++++++++++-- 7 files changed, 49 insertions(+), 38 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java index 9e32f371b8..7ef1377441 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java @@ -42,6 +42,7 @@ import com.oracle.graal.python.builtins.modules.ImpModuleBuiltins.ExecBuiltin; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; +import com.oracle.graal.python.builtins.objects.function.Signature; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; @@ -49,7 +50,6 @@ import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.runtime.object.PFactory; import com.oracle.graal.python.util.BiConsumer; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.strings.TruffleString; @@ -108,11 +108,12 @@ public void initialize(Python3Core core) { } TruffleString tsName = toInternedTruffleStringUncached(builtin.name()); PythonLanguage language = core.getLanguage(); - RootCallTarget callTarget = language.initBuiltinCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), factory.getNodeClass(), - builtin.name()); Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : toTruffleStringUncached(builtin.doc()); - int flags = PBuiltinFunction.getFlags(builtin, callTarget); - PBuiltinFunction function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, callTarget); + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.initBuiltinRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), + factory.getNodeClass(), builtin.name()); + Signature signature = rootNode.getSignature(); + int flags = PBuiltinFunction.getFlags(builtin, signature); + PBuiltinFunction function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, rootNode, true); function.setAttribute(T___DOC__, builtinDoc); BoundBuiltinCallable callable = function; if (builtin.isGetter() || builtin.isSetter()) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java index 796d661a83..46529dbfe9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java @@ -91,7 +91,6 @@ import com.oracle.graal.python.util.PythonUtils.PrototypeNodeFactory; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateInline; @@ -251,11 +250,11 @@ Object doGeneric(@SuppressWarnings("unused") VirtualFrame frame, Object self, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Object owner, TruffleString propertyName, int type, int offset) { CExtToJavaNode asPythonObjectNode = getReadConverterNode(type); - RootCallTarget callTarget = language.createCachedPropAccessCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedPropAccessRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadMemberNodeGen.create(type, offset, asPythonObjectNode)), true), ReadMemberNode.class, BUILTIN.name(), type, offset); - int flags = PBuiltinFunction.getFlags(BUILTIN, callTarget); - return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, callTarget); + int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); + return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode, false); } } @@ -277,11 +276,11 @@ Object doGeneric(Object self, Object value, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString propertyName) { - RootCallTarget builtinCt = language.createCachedCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadOnlyMemberNodeGen.create(propertyName)), true), ReadOnlyMemberNode.class, BUILTIN.name()); - int flags = PBuiltinFunction.getFlags(BUILTIN, builtinCt); - return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, builtinCt); + int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); + return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode, false); } } @@ -301,11 +300,11 @@ static Object doGeneric(Object self, @SuppressWarnings("unused") Object value, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString propertyName) { - RootCallTarget builtinCt = language.createCachedCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(BadMemberDescrNodeGen.create()), true), BadMemberDescrNode.class, BUILTIN.name()); - int flags = PBuiltinFunction.getFlags(BUILTIN, builtinCt); - return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, builtinCt); + int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); + return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode, false); } } @@ -600,11 +599,11 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Ob return BadMemberDescrNode.createBuiltinFunction(language, propertyName); } // - RootCallTarget callTarget = language.createCachedPropAccessCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedPropAccessRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(WriteMemberNodeGen.create(type, offset)), true), WriteMemberNode.class, BUILTIN.name(), type, offset); - int flags = PBuiltinFunction.getFlags(BUILTIN, callTarget); - return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, callTarget); + int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); + return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode, false); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java index 537008db32..495cbc5e3c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.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 @@ -81,7 +81,6 @@ import com.oracle.graal.python.runtime.object.PFactory; import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.strings.TruffleString; @@ -224,8 +223,8 @@ private static void copyMethod(PythonLanguage language, PythonAbstractClass klas } private static void createMember(PythonLanguage language, Object klass, TruffleString name, TruffleString doc, int idx) { - RootCallTarget callTarget = language.createStructSeqIndexedMemberAccessCachedCallTarget((l) -> new GetStructMemberNode(l, idx), idx); - PBuiltinFunction getter = PFactory.createBuiltinFunction(language, name, klass, 0, 0, callTarget); + GetStructMemberNode rootNode = (GetStructMemberNode) language.createStructSeqIndexedMemberAccessCachedRootNode((l) -> new GetStructMemberNode(l, idx), idx); + PBuiltinFunction getter = PFactory.createBuiltinFunction(language, name, klass, 0, 0, rootNode, false); GetSetDescriptor callable = PFactory.createGetSetDescriptor(language, getter, null, name, klass, false); if (doc != null) { callable.setAttribute(T___DOC__, doc); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index ff923f403a..1ed752fa93 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -2328,9 +2328,9 @@ private static void addDictDescrAttribute(PythonAbstractClass[] basesArray, Pyth // initialized yet if ((!hasPythonClassBases(basesArray) && LookupAttributeInMRONode.lookupSlowPath(pythonClass, T___DICT__) == PNone.NO_VALUE) || basesHaveSlots(basesArray)) { Builtin dictBuiltin = ObjectBuiltins.DictNode.class.getAnnotation(Builtin.class); - RootCallTarget callTarget = PythonLanguage.get(null).createCachedCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) PythonLanguage.get(null).createCachedRootNode( l -> new BuiltinFunctionRootNode(l, dictBuiltin, ObjectBuiltinsFactory.DictNodeFactory.getInstance(), true), ObjectBuiltins.DictNode.class); - setAttribute(T___DICT__, dictBuiltin, callTarget, pythonClass, language); + setAttribute(T___DICT__, dictBuiltin, rootNode, pythonClass, language); } } @@ -2338,9 +2338,9 @@ private static void addDictDescrAttribute(PythonAbstractClass[] basesArray, Pyth private static void addWeakrefDescrAttribute(PythonClass pythonClass, PythonLanguage language) { if (LookupAttributeInMRONode.lookupSlowPath(pythonClass, T___WEAKREF__) == PNone.NO_VALUE) { Builtin builtin = GetWeakRefsNode.class.getAnnotation(Builtin.class); - RootCallTarget callTarget = PythonLanguage.get(null).createCachedCallTarget( + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) PythonLanguage.get(null).createCachedRootNode( l -> new BuiltinFunctionRootNode(l, builtin, WeakRefModuleBuiltinsFactory.GetWeakRefsNodeFactory.getInstance(), true), GetWeakRefsNode.class); - setAttribute(T___WEAKREF__, builtin, callTarget, pythonClass, language); + setAttribute(T___WEAKREF__, builtin, rootNode, pythonClass, language); } } @@ -2351,6 +2351,13 @@ private static void setAttribute(TruffleString name, Builtin builtin, RootCallTa pythonClass.setAttribute(name, desc); } + private static void setAttribute(TruffleString name, Builtin builtin, BuiltinFunctionRootNode rootNode, PythonClass pythonClass, PythonLanguage language) { + int flags = PBuiltinFunction.getFlags(builtin, rootNode.getSignature()); + PBuiltinFunction function = PFactory.createBuiltinFunction(language, name, pythonClass, 1, flags, rootNode, false); + GetSetDescriptor desc = PFactory.createGetSetDescriptor(language, function, function, name, pythonClass, true); + pythonClass.setAttribute(name, desc); + } + private static boolean basesHaveSlots(PythonAbstractClass[] basesArray) { // this is merely based on empirical observation // see also test_type.py#test_dict() diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/CallDispatchers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/CallDispatchers.java index f53d5afb22..5f5628e329 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/CallDispatchers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/CallDispatchers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 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 @@ -51,7 +51,6 @@ import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.argument.CreateArgumentsNode; import com.oracle.graal.python.nodes.call.CallDispatchersFactory.FunctionIndirectInvokeNodeGen; -import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; import com.oracle.graal.python.runtime.ExecutionContext; import com.oracle.graal.python.runtime.ExecutionContext.IndirectCalleeContext; import com.oracle.graal.python.runtime.PythonContext; @@ -83,8 +82,7 @@ public class CallDispatchers { @NeverDefault public static DirectCallNode createDirectCallNodeFor(PBuiltinFunction callee) { DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(callee.getCallTarget()); - if (PythonLanguage.get(null).getEngineOption(PythonOptions.EnableForcedSplits) || - (callee.getFunctionRootNode() instanceof BuiltinFunctionRootNode root && root.getBuiltin().forceSplitDirectCalls())) { + if (PythonLanguage.get(null).getEngineOption(PythonOptions.EnableForcedSplits) || callee.forceSplitDirectCalls()) { callNode.cloneCallTarget(); } return callNode; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/AbstractCallMethodNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/AbstractCallMethodNode.java index 6f05ec45a5..ef35d0ed11 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/AbstractCallMethodNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/AbstractCallMethodNode.java @@ -50,7 +50,6 @@ import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.builtins.FunctionNodes.GetCallTargetNode; -import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryBuiltinNode; @@ -64,7 +63,6 @@ import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; @ImportStatic({PythonOptions.class, PGuards.class}) @NodeField(name = "maxSizeExceeded", type = boolean.class) @@ -150,10 +148,7 @@ private boolean callerExceedsMaxSize(T builtin protected static boolean takesSelfArg(Object func) { if (func instanceof PBuiltinFunction) { - RootNode functionRootNode = ((PBuiltinFunction) func).getFunctionRootNode(); - if (functionRootNode instanceof BuiltinFunctionRootNode) { - return ((BuiltinFunctionRootNode) functionRootNode).declaresExplicitSelf(); - } + return ((PBuiltinFunction) func).declaresExplicitSelf(); } else if (func instanceof PBuiltinMethod) { return takesSelfArg(((PBuiltinMethod) func).getFunction()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java index df419f01da..eeb4f6735a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java @@ -758,8 +758,8 @@ public static Object[] toArray(List list) { public static PBuiltinFunction createMethod(PythonLanguage language, Object klass, NodeFactory nodeFactory, Object type, int numDefaults) { Class nodeClass = nodeFactory.getNodeClass(); Builtin builtin = nodeClass.getAnnotation(Builtin.class); - RootCallTarget callTarget = language.createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, nodeFactory, true), nodeClass); - return createMethod(klass, builtin, callTarget, type, numDefaults); + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, nodeFactory, true), nodeClass); + return createMethod(klass, builtin, rootNode, type, numDefaults); } @TruffleBoundary @@ -776,6 +776,18 @@ public static PBuiltinFunction createMethod(Object klass, Builtin builtin, RootC return function; } + @TruffleBoundary + public static PBuiltinFunction createMethod(Object klass, Builtin builtin, BuiltinFunctionRootNode rootNode, Object type, int numDefaults) { + assert rootNode.getBuiltin() == builtin : String.format("%s != %s, klass: %s", rootNode.getBuiltin(), builtin, klass); + int flags = PBuiltinFunction.getFlags(builtin, rootNode.getSignature()); + TruffleString name = toInternedTruffleStringUncached(builtin.name()); + PBuiltinFunction function = PFactory.createBuiltinFunction(PythonLanguage.get(null), name, type, numDefaults, flags, rootNode, false); + if (klass != null) { + WriteAttributeToObjectNode.getUncached().execute(klass, name, function); + } + return function; + } + public static Unsafe initUnsafe() { try { return Unsafe.getUnsafe(); From 225de1dfb483ae2a3aa3e3d360ef9a311fc4011b Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 14:40:39 +0200 Subject: [PATCH 03/26] Convert child code objects to shared roots --- .../runtime/LazyBuiltinCallTargetTests.java | 108 ++++++++++++++++++ .../builtins/objects/code/CodeNodes.java | 3 +- .../nodes/bytecode/PBytecodeRootNode.java | 4 +- 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java diff --git a/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java b/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java new file mode 100644 index 0000000000..0a0a7b5454 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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 + * + * 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. + */ +package com.oracle.graal.python.test.runtime; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.junit.Test; + +import com.oracle.graal.python.builtins.objects.code.PCode; +import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; + +public class LazyBuiltinCallTargetTests { + + @Test + public void builtinCallTargetsRemainLazyAfterStartup() { + int totalBefore = PBuiltinFunction.getTrackedBuiltinFunctionCount(); + int callTargetsBefore = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); + try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); + Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { + assertEquals(0, context.eval("python", "0").asInt()); + } + int totalDelta = PBuiltinFunction.getTrackedBuiltinFunctionCount() - totalBefore; + int callTargetDelta = PBuiltinFunction.getTrackedBuiltinCallTargetCount() - callTargetsBefore; + assertTrue(String.format("expected tracked builtin functions to be registered during startup, totalDelta=%d", totalDelta), totalDelta > 0); + assertTrue(String.format("expected fewer builtin call targets than builtin functions to be initialized during startup, totalDelta=%d callTargetDelta=%d", totalDelta, callTargetDelta), + callTargetDelta < totalDelta); + } + + @Test + public void builtinCallTargetsInitializeOnFirstUse() { + try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); + Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { + assertEquals(0, context.eval("python", "0").asInt()); + int beforeCalls = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); + assertEquals(0, context.eval("python", "abs(-42)\n[].append(1)\n0").asInt()); + int afterCalls = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); + assertTrue(String.format("expected builtin calls to initialize at least one lazy call target, before=%d after=%d", beforeCalls, afterCalls), afterCalls > beforeCalls); + } + } + + @Test + public void codeCallTargetsRemainLazyAfterFunctionDefinition() { + int totalBefore = PCode.getTrackedCodeCount(); + int callTargetsBefore = PCode.getTrackedCodeCallTargetCount(); + try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); + Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { + assertEquals(0, context.eval("python", "def f():\n return 1\n0").asInt()); + } + int totalDelta = PCode.getTrackedCodeCount() - totalBefore; + int callTargetDelta = PCode.getTrackedCodeCallTargetCount() - callTargetsBefore; + assertTrue(String.format("expected tracked child code objects to be created, totalDelta=%d", totalDelta), totalDelta > 0); + assertTrue(String.format("expected fewer code call targets than tracked code objects after definition, totalDelta=%d callTargetDelta=%d", totalDelta, callTargetDelta), + callTargetDelta < totalDelta); + } + + @Test + public void codeCallTargetsInitializeOnFirstInvocation() { + try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); + Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { + assertEquals(0, context.eval("python", "def f():\n return 1\n0").asInt()); + int beforeCalls = PCode.getTrackedCodeCallTargetCount(); + assertEquals(1, context.eval("python", "f()").asInt()); + int afterCalls = PCode.getTrackedCodeCallTargetCount(); + assertTrue(String.format("expected code invocation to initialize at least one lazy call target, before=%d after=%d", beforeCalls, afterCalls), afterCalls > beforeCalls); + } + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java index ac5e582732..7ee22b3c4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java @@ -144,7 +144,7 @@ private static PCode createCode(PythonLanguage language, int argCount, RootCallTarget ct; Signature signature; if (codedata.length == 0) { - ct = language.createCachedCallTarget(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); + PRootNode rootNode = (PRootNode) language.createCachedRootNode(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); /* * We need to create a proper signature because this code path is used to create * fake code objects for duck-typed function-like objects, such as Cython functions. @@ -165,6 +165,7 @@ private static PCode createCode(PythonLanguage language, int argCount, varArgsIndex, parameterNames, kwOnlyNames); + return PFactory.createCode(language, rootNode, signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); } else { ct = deserializeForBytecodeInterpreter(language, codedata, cellvars, freevars, flags); signature = ((PRootNode) ct.getRootNode()).getSignature(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java index 4930eae2f5..1d9e7c6248 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java @@ -246,7 +246,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.HostCompilerDirectives.BytecodeInterpreterSwitch; import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -2919,10 +2918,9 @@ public void materializeContainedFunctionsForInstrumentation(Set PBytecodeRootNode.createMaybeGenerator(language, codeUnit, getSource(), isInternal()), codeUnit); - RootNode rootNode = callTarget.getRootNode(); if (rootNode instanceof PBytecodeGeneratorFunctionRootNode) { rootNode = ((PBytecodeGeneratorFunctionRootNode) rootNode).getBytecodeRootNode(); } From af6d928ad7f89d6d2354d2f552aa058edf696733 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 14:43:46 +0200 Subject: [PATCH 04/26] Lazily materialize builtin slot call targets --- .../python/builtins/objects/type/slots/TpSlot.java | 10 +++++----- .../builtins/objects/type/slots/TpSlotBinaryFunc.java | 3 +-- .../builtins/objects/type/slots/TpSlotBinaryOp.java | 3 +-- .../builtins/objects/type/slots/TpSlotDescrGet.java | 3 +-- .../builtins/objects/type/slots/TpSlotDescrSet.java | 3 +-- .../builtins/objects/type/slots/TpSlotGetAttr.java | 3 +-- .../builtins/objects/type/slots/TpSlotHashFun.java | 3 +-- .../builtins/objects/type/slots/TpSlotInquiry.java | 3 +-- .../builtins/objects/type/slots/TpSlotIterNext.java | 3 +-- .../python/builtins/objects/type/slots/TpSlotLen.java | 3 +-- .../objects/type/slots/TpSlotMpAssSubscript.java | 3 +-- .../builtins/objects/type/slots/TpSlotNbPower.java | 3 +-- .../builtins/objects/type/slots/TpSlotRichCompare.java | 3 +-- .../builtins/objects/type/slots/TpSlotSetAttr.java | 3 +-- .../builtins/objects/type/slots/TpSlotSizeArgFun.java | 3 +-- .../builtins/objects/type/slots/TpSlotSqAssItem.java | 3 +-- .../builtins/objects/type/slots/TpSlotUnaryFunc.java | 3 +-- .../builtins/objects/type/slots/TpSlotVarargs.java | 7 +++---- 18 files changed, 24 insertions(+), 41 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java index 1474f74336..99a1113df1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java @@ -309,10 +309,10 @@ final PBuiltinFunction createBuiltin(Python3Core core, Object type, TruffleStrin Class nodeClass = NodeFactoryBase.getWrappedNodeClass(factory); validateSlotNode(factory, nodeClass, slotSignature); PythonBuiltinClassType builtinType = type instanceof PythonBuiltinClassType bt ? bt : null; - RootCallTarget callTarget = core.getLanguage().createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, true, builtinType), factory.getNodeClass(), nodeClass, - builtinType, name); + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) core.getLanguage().createCachedRootNode( + l -> new BuiltinFunctionRootNode(l, builtin, factory, true, builtinType), factory.getNodeClass(), nodeClass, builtinType, name); - PBuiltinFunction function = PFactory.createWrapperDescriptor(core.getLanguage(), tsName, type, numDefaults(builtin), 0, callTarget, this, wrapper); + PBuiltinFunction function = PFactory.createWrapperDescriptor(core.getLanguage(), tsName, type, numDefaults(builtin), 0, rootNode, this, wrapper); function.setAttribute(T___DOC__, SlotWrapperDocstrings.getDocstring(name)); return function; } @@ -322,12 +322,12 @@ final PBuiltinFunction createBuiltin(Python3Core core, Object type, TruffleStrin * {@link #initialize(PythonLanguage)} to create the slot call target if the slot node can * be wrapped by {@link BuiltinFunctionRootNode}. */ - static RootCallTarget createSlotCallTarget(PythonLanguage language, BuiltinSlotWrapperSignature signature, NodeFactory factory, String name) { + static BuiltinFunctionRootNode createSlotRootNode(PythonLanguage language, BuiltinSlotWrapperSignature signature, NodeFactory factory, String name) { SlotSignature slotSignature = factory.getNodeClass().getAnnotation(SlotSignature.class); Builtin builtin = new Slot2Builtin(slotSignature, name, signature); Class nodeClass = NodeFactoryBase.getWrappedNodeClass(factory); validateSlotNode(factory, nodeClass, slotSignature); - return language.createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, true), factory.getNodeClass(), nodeClass, name); + return (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, true), factory.getNodeClass(), nodeClass, name); } private static void validateSlotNode(NodeFactory factory, Class nodeClass, SlotSignature slotSignature) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryFunc.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryFunc.java index 379ebab99c..0cd49cba36 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryFunc.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryFunc.java @@ -99,8 +99,7 @@ final PythonBinaryBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), builtinName); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), builtinName)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryOp.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryOp.java index 5bfa9e2226..aa974134a6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryOp.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotBinaryOp.java @@ -246,8 +246,7 @@ final BinaryOpBuiltinNode createOpSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), builtinName); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), builtinName)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrGet.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrGet.java index 14495445b8..53b0239c54 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrGet.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrGet.java @@ -149,8 +149,7 @@ protected TpSlotDescrGetBuiltinComplex(NodeFactory nodeFactory) { public void initialize(PythonLanguage language) { // We need a different call-target for the "raw" slot. It must not normalize None to // NO_VALUE (NULL in CPython) like the __get__ wrapper. - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), J___GET__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), J___GET__)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrSet.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrSet.java index f3d0fc8af9..21b2ab5c7c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrSet.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrSet.java @@ -118,8 +118,7 @@ final DescrSetBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, SET_SIGNATURE, getNodeFactory(), J___SET__); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SET_SIGNATURE, getNodeFactory(), J___SET__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotGetAttr.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotGetAttr.java index 048b9d0087..3d3ae4267b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotGetAttr.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotGetAttr.java @@ -120,8 +120,7 @@ final GetAttrBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), J___GETATTRIBUTE__); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), J___GETATTRIBUTE__)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotHashFun.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotHashFun.java index b6aac455d3..69f5c89176 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotHashFun.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotHashFun.java @@ -134,8 +134,7 @@ HashBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), J___HASH__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), J___HASH__)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotInquiry.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotInquiry.java index 3268aaa9c1..8c6bd1f099 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotInquiry.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotInquiry.java @@ -123,8 +123,7 @@ protected TpSlotInquiryBuiltinComplex(NodeFactory nodeFactory) { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), J___BOOL__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), J___BOOL__)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotIterNext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotIterNext.java index 59efb7052f..b4560e1c81 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotIterNext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotIterNext.java @@ -114,8 +114,7 @@ final PythonUnaryBuiltinNode createSlotNode() { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, BuiltinSlotWrapperSignature.UNARY, getNodeFactory(), J___NEXT__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.UNARY, getNodeFactory(), J___NEXT__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotLen.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotLen.java index cb8fed064e..171c1dd639 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotLen.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotLen.java @@ -133,8 +133,7 @@ protected TpSlotLenBuiltinComplex(NodeFactory nodeFactory) { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), J___LEN__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), J___LEN__)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotMpAssSubscript.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotMpAssSubscript.java index a7e57d6c06..dd4d651f1a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotMpAssSubscript.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotMpAssSubscript.java @@ -112,8 +112,7 @@ final MpAssSubscriptBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, SET_SIGNATURE, getNodeFactory(), J___SETITEM__); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SET_SIGNATURE, getNodeFactory(), J___SETITEM__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotNbPower.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotNbPower.java index 333af4b608..454c52dda9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotNbPower.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotNbPower.java @@ -113,8 +113,7 @@ final PythonTernaryBuiltinNode createOpSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), J___POW__); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), J___POW__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotRichCompare.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotRichCompare.java index c5cd3529e2..b8fcaaf5c1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotRichCompare.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotRichCompare.java @@ -137,8 +137,7 @@ protected TpSlotRichCmpBuiltinComplex(NodeFactory nodeFactory) { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, SIGNATURE, getNodeFactory(), "tp_richcompare"); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SIGNATURE, getNodeFactory(), "tp_richcompare")); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSetAttr.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSetAttr.java index 81f50bee0a..1ffcaef0f1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSetAttr.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSetAttr.java @@ -125,8 +125,7 @@ final SetAttrBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, SET_SIGNATURE, getNodeFactory(), J___SETATTR__); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SET_SIGNATURE, getNodeFactory(), J___SETATTR__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSizeArgFun.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSizeArgFun.java index 23e641aaf9..6be12fad54 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSizeArgFun.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSizeArgFun.java @@ -112,8 +112,7 @@ final SizeArgFunBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), name); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.BINARY, getNodeFactory(), name)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSqAssItem.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSqAssItem.java index f818060fdc..c4933fabc7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSqAssItem.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSqAssItem.java @@ -119,8 +119,7 @@ final SqAssItemBuiltinNode createSlotNode() { @Override public void initialize(PythonLanguage language) { - RootCallTarget target = createSlotCallTarget(language, SET_SIGNATURE, getNodeFactory(), J___SETITEM__); - language.setBuiltinSlotCallTarget(callTargetIndex, target); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, SET_SIGNATURE, getNodeFactory(), J___SETITEM__)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotUnaryFunc.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotUnaryFunc.java index 04ed4ec5d5..fb1832e1be 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotUnaryFunc.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotUnaryFunc.java @@ -97,8 +97,7 @@ final PythonUnaryBuiltinNode createSlotNode() { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, BuiltinSlotWrapperSignature.UNARY, getNodeFactory(), builtinName); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, BuiltinSlotWrapperSignature.UNARY, getNodeFactory(), builtinName)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java index fd7a8d2ac1..dc440388fb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java @@ -181,8 +181,7 @@ public TruffleString getName() { @Override public final void initialize(PythonLanguage language) { - RootCallTarget callTarget = createSlotCallTarget(language, null, getNodeFactory(), name); - language.setBuiltinSlotCallTarget(callTargetIndex, callTarget); + language.setBuiltinSlotRootNode(callTargetIndex, createSlotRootNode(language, null, getNodeFactory(), name)); } @Override @@ -213,9 +212,9 @@ public PBuiltinMethod createBuiltin(Python3Core core, Object type, TruffleString * 'WrapTpNew' holds the type in a field and uses that to do the check. The dropping is * achieved by using `declaresExplicitSelf = false`. */ - RootCallTarget callTarget = language.createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, false, builtinType), + BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, false, builtinType), nodeClass, nodeClass, builtinType, J___NEW__); - return PFactory.createNewWrapper(language, type, defaults, kwDefaults, callTarget, this); + return PFactory.createNewWrapper(language, type, defaults, kwDefaults, rootNode, this); } } From 2766ae63c87a368be3eabde6b548bbd90fb02419 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 14:46:16 +0200 Subject: [PATCH 05/26] Convert cext wrappers and async handler to roots --- .../modules/cext/PythonCextTypeBuiltins.java | 18 +++++++++--------- .../builtins/objects/cext/capi/CExtNodes.java | 6 +++--- .../cext/capi/ExternalFunctionNodes.java | 13 ++++++------- .../cext/capi/MethodDescriptorWrapper.java | 11 +++++------ .../graal/python/runtime/AsyncHandler.java | 11 +++++++---- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java index 908ad9da5d..023deb5b55 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java @@ -110,6 +110,7 @@ import com.oracle.graal.python.nodes.ErrorMessages; import com.oracle.graal.python.nodes.HiddenAttr; import com.oracle.graal.python.nodes.PRaiseNode; +import com.oracle.graal.python.nodes.PRootNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.attributes.WriteAttributeToPythonObjectNode; import com.oracle.graal.python.nodes.object.GetDictIfExistsNode; @@ -124,7 +125,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -392,17 +392,17 @@ public static GetSetDescriptor createGetSet(TruffleString name, Object cls, long PBuiltinFunction get = null; PythonLanguage language = PythonLanguage.get(null); if (getter != NULLPTR) { - RootCallTarget getterCT = getterCallTarget(name, language); + PRootNode getterRoot = getterRootNode(name, language); NativeFunctionPointer getterFun = CExtCommonNodes.bindFunctionPointer(getter, PExternalFunctionWrapper.GETTER); - get = PFactory.createBuiltinFunction(language, name, cls, EMPTY_OBJECT_ARRAY, ExternalFunctionNodes.createKwDefaults(getterFun, closure), 0, getterCT); + get = PFactory.createBuiltinFunction(language, name, cls, EMPTY_OBJECT_ARRAY, ExternalFunctionNodes.createKwDefaults(getterFun, closure), 0, getterRoot); } PBuiltinFunction set = null; boolean hasSetter = setter != NULLPTR; if (hasSetter) { - RootCallTarget setterCT = setterCallTarget(name, language); + PRootNode setterRoot = setterRootNode(name, language); NativeFunctionPointer setterFun = CExtCommonNodes.bindFunctionPointer(setter, PExternalFunctionWrapper.SETTER); - set = PFactory.createBuiltinFunction(language, name, cls, EMPTY_OBJECT_ARRAY, ExternalFunctionNodes.createKwDefaults(setterFun, closure), 0, setterCT); + set = PFactory.createBuiltinFunction(language, name, cls, EMPTY_OBJECT_ARRAY, ExternalFunctionNodes.createKwDefaults(setterFun, closure), 0, setterRoot); } GetSetDescriptor descriptor = PFactory.createGetSetDescriptor(language, get, set, name, cls, hasSetter); @@ -411,15 +411,15 @@ public static GetSetDescriptor createGetSet(TruffleString name, Object cls, long } @TruffleBoundary - private static RootCallTarget getterCallTarget(TruffleString name, PythonLanguage lang) { + private static PRootNode getterRootNode(TruffleString name, PythonLanguage lang) { Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.GETTER); - return lang.createCachedExternalFunWrapperCallTarget(rootNodeFunction, GetterRoot.class, PExternalFunctionWrapper.GETTER, name, true, false); + return (PRootNode) lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, GetterRoot.class, PExternalFunctionWrapper.GETTER, name, true, false); } @TruffleBoundary - private static RootCallTarget setterCallTarget(TruffleString name, PythonLanguage lang) { + private static PRootNode setterRootNode(TruffleString name, PythonLanguage lang) { Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.SETTER); - return lang.createCachedExternalFunWrapperCallTarget(rootNodeFunction, SetterRoot.class, PExternalFunctionWrapper.SETTER, name, true, false); + return (PRootNode) lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, SetterRoot.class, PExternalFunctionWrapper.SETTER, name, true, false); } @CApiBuiltin(ret = ArgDescriptor.Void, args = {PyTypeObject, PyBufferProcs}, call = Ignored) 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 1eac8e6890..655b4cfa27 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 @@ -143,6 +143,7 @@ import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.PRaiseNode; +import com.oracle.graal.python.nodes.PRootNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -164,7 +165,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -1193,10 +1193,10 @@ static PBuiltinFunction createLegacyMethod(long methodDefPtr, int element, Pytho // CPy-style methods // TODO(fa) support static and class methods MethodDescriptorWrapper sig = MethodDescriptorWrapper.fromMethodFlags(flags); - RootCallTarget callTarget = MethodDescriptorWrapper.getOrCreateCallTarget(language, sig, methodName, CExtContext.isMethStatic(flags)); + PRootNode rootNode = MethodDescriptorWrapper.getOrCreateRootNode(language, sig, methodName, CExtContext.isMethStatic(flags)); NativeFunctionPointer fun = CExtCommonNodes.bindFunctionPointer(mlMethObj, sig); PKeyword[] kwDefaults = ExternalFunctionNodes.createKwDefaults(fun); - PBuiltinFunction function = PFactory.createBuiltinFunction(language, methodName, null, PythonUtils.EMPTY_OBJECT_ARRAY, kwDefaults, flags, callTarget); + PBuiltinFunction function = PFactory.createBuiltinFunction(language, methodName, null, PythonUtils.EMPTY_OBJECT_ARRAY, kwDefaults, flags, rootNode); HiddenAttr.WriteLongNode.executeUncached(function, METHOD_DEF_PTR, methodDefPtr); // write doc string; we need to directly write to the storage otherwise it is disallowed diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java index 0a309b63dd..10e0584da5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java @@ -168,7 +168,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -482,8 +481,8 @@ public enum PExternalFunctionWrapper implements NativeCExtSymbol { } @TruffleBoundary - static RootCallTarget getOrCreateCallTarget(PExternalFunctionWrapper sig, PythonLanguage language, TruffleString name) { - return language.createCachedExternalFunWrapperCallTarget(l -> WrapperDescriptorRootNodesGen.create(l, name, sig), sig.rootNodeClass, sig, name, true, false); + static PRootNode getOrCreateRootNode(PExternalFunctionWrapper sig, PythonLanguage language, TruffleString name) { + return (PRootNode) language.createCachedExternalFunWrapperRootNode(l -> WrapperDescriptorRootNodesGen.create(l, name, sig), sig.rootNodeClass, sig, name, true, false); } /** @@ -495,7 +494,7 @@ static RootCallTarget getOrCreateCallTarget(PExternalFunctionWrapper sig, Python * @param name The name of the method. * @param callable A reference denoting executable code. Currently, there are two * representations for that: a native function pointer or a - * {@link RootCallTarget} + * {@link PRootNode} * @param enclosingType The type the function belongs to (needed for checking of * {@code self}). * @param sig The wrapper/signature ID as defined in {@link PExternalFunctionWrapper}. @@ -506,7 +505,7 @@ static RootCallTarget getOrCreateCallTarget(PExternalFunctionWrapper sig, Python @TruffleBoundary public static PythonBuiltinObject createDescrWrapperFunction(TruffleString name, NativeFunctionPointer callable, Object enclosingType, PExternalFunctionWrapper sig, PythonLanguage language) { LOGGER.finer(() -> PythonUtils.formatJString("ExternalFunctions.createDescrWrapperFunction(%s, %s)", name, callable)); - RootCallTarget callTarget = getOrCreateCallTarget(sig, language, name); + PRootNode rootNode = getOrCreateRootNode(sig, language, name); // ensure that 'callable' is executable via InteropLibrary PKeyword[] kwDefaults = ExternalFunctionNodes.createKwDefaults(callable); @@ -517,9 +516,9 @@ public static PythonBuiltinObject createDescrWrapperFunction(TruffleString name, Object type = enclosingType == PNone.NO_VALUE ? null : enclosingType; if (sig == NEW) { - return PFactory.createNewWrapper(language, type, defaults, kwDefaults, callTarget, slot); + return PFactory.createNewWrapper(language, type, defaults, kwDefaults, rootNode, slot); } - return PFactory.createWrapperDescriptor(language, name, type, defaults, kwDefaults, 0, callTarget, slot, sig); + return PFactory.createWrapperDescriptor(language, name, type, defaults, kwDefaults, 0, rootNode, slot, sig); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java index 0e1908e3d8..c82fe409ab 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java @@ -67,7 +67,6 @@ 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.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.strings.TruffleString; @@ -125,7 +124,7 @@ public ArgDescriptor[] getArguments() { private static final TruffleLogger LOGGER = CApiContext.getLogger(MethodDescriptorWrapper.class); @TruffleBoundary - static RootCallTarget getOrCreateCallTarget(PythonLanguage language, MethodDescriptorWrapper sig, TruffleString name, boolean isStatic) { + static PRootNode getOrCreateRootNode(PythonLanguage language, MethodDescriptorWrapper sig, TruffleString name, boolean isStatic) { Class nodeKlass; Function rootNodeFunction = switch (sig) { case KEYWORDS -> { @@ -157,7 +156,7 @@ static RootCallTarget getOrCreateCallTarget(PythonLanguage language, MethodDescr yield (l -> new MethMethodRoot(l, name, isStatic, sig)); } }; - return language.createCachedExternalFunWrapperCallTarget(rootNodeFunction, nodeKlass, sig, name, true, isStatic); + return (PRootNode) language.createCachedExternalFunWrapperRootNode(rootNodeFunction, nodeKlass, sig, name, true, isStatic); } /** @@ -168,7 +167,7 @@ static RootCallTarget getOrCreateCallTarget(PythonLanguage language, MethodDescr * @param language The Python language object. * @param name The name of the method. * @param callable A reference denoting executable code. Currently, there are two - * representations for that: a native function pointer or a {@link RootCallTarget} + * representations for that: a native function pointer or a {@link PRootNode} * @param enclosingType The type the function belongs to (needed for checking of {@code self}). * @return A {@link PBuiltinFunction} implementing the semantics of the specified slot wrapper. */ @@ -180,7 +179,7 @@ public static PBuiltinFunction createWrapperFunction(PythonLanguage language, Tr return null; } - RootCallTarget callTarget = getOrCreateCallTarget(language, methodDescriptorWrapper, name, CExtContext.isMethStatic(flags)); + PRootNode rootNode = getOrCreateRootNode(language, methodDescriptorWrapper, name, CExtContext.isMethStatic(flags)); PKeyword[] kwDefaults = ExternalFunctionNodes.createKwDefaults(CExtCommonNodes.bindFunctionPointer(callable, methodDescriptorWrapper)); @@ -188,7 +187,7 @@ public static PBuiltinFunction createWrapperFunction(PythonLanguage language, Tr Object[] defaults = PBuiltinFunction.generateDefaults(0); Object type = enclosingType == PNone.NO_VALUE ? null : enclosingType; - return PFactory.createBuiltinFunction(language, name, type, defaults, kwDefaults, flags, callTarget); + return PFactory.createBuiltinFunction(language, name, type, defaults, kwDefaults, flags, rootNode); } /** diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 82e97615d9..103f383a8e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -73,7 +73,6 @@ import com.oracle.graal.python.util.SuppressFBWarnings; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.ThreadLocalAction; import com.oracle.truffle.api.ThreadLocalAction.Access; import com.oracle.truffle.api.TruffleLanguage; @@ -201,7 +200,7 @@ public final void execute(PythonContext context, Access access) { } } try { - CallDispatchers.SimpleIndirectInvokeNode.executeUncached(context.getAsyncHandler().callTarget, args); + CallDispatchers.SimpleIndirectInvokeNode.executeUncached(context.getAsyncHandler().getCallTarget(), args); } catch (PException e) { handleException(e); } finally { @@ -341,11 +340,11 @@ public boolean setsUpCalleeContext() { } } - private final RootCallTarget callTarget; + private final CallRootNode rootNode; AsyncHandler(PythonContext context) { this.context = new WeakReference<>(context); - this.callTarget = context.getLanguage().createCachedCallTarget(CallRootNode::new, CallRootNode.class); + this.rootNode = (CallRootNode) context.getLanguage().createCachedRootNode(CallRootNode::new, CallRootNode.class); if (PythonOptions.AUTOMATIC_ASYNC_ACTIONS) { this.executorService = Executors.newScheduledThreadPool(6, runnable -> { Thread t = Executors.defaultThreadFactory().newThread(runnable); @@ -380,6 +379,10 @@ void registerAction(Supplier actionSupplier) { } } + private com.oracle.truffle.api.RootCallTarget getCallTarget() { + return rootNode.getCallTarget(); + } + void poll() { if (!PythonOptions.AUTOMATIC_ASYNC_ACTIONS) { for (AsyncRunnable r : registeredActions) { From 72093af37f5148fef475b508711fb1ad5a5eaab4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 30 Apr 2026 14:50:24 +0200 Subject: [PATCH 06/26] Remove obsolete lazy call-target helper APIs --- .../oracle/graal/python/PythonLanguage.java | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 01c9739697..dae9c29f0b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -1091,12 +1091,6 @@ public RootCallTarget getBuiltinSlotCallTarget(int index) { return callTarget; } - public void setBuiltinSlotCallTarget(int index, RootCallTarget callTarget) { - VarHandle.storeStoreFence(); - builtinSlotsCallTargets[index] = callTarget; - builtinSlotsRootNodes[index] = callTarget != null ? callTarget.getRootNode() : null; - } - public void setBuiltinSlotRootNode(int index, RootNode rootNode) { VarHandle.storeStoreFence(); builtinSlotsRootNodes[index] = rootNode; @@ -1163,12 +1157,6 @@ public RootNode createCachedRootNode(Function rootNode return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } - // Variant that should be called at most once per context, because it does not cache the target - // in single context mode - public RootCallTarget initBuiltinCallTarget(Function rootNodeFunction, Class nodeClass, String key) { - return createCachedCallTargetUnsafe(rootNodeFunction, false, nodeClass, key); - } - // Variant that should be called at most once per context, because it does not cache the root // node in single context mode public RootNode initBuiltinRootNode(Function rootNodeFunction, Class nodeClass, String key) { @@ -1219,19 +1207,6 @@ public RootNode createCachedRootNode(Function rootNode return createCachedRootNodeUnsafe(rootNodeFunction, true, key); } - /** - * Caches call targets for external C functions created by extensions at runtime. - *

- * For the time being, we assume finite/limited number of extensions and their external - * functions. This may hold onto call targets created by one extension used in a context that - * was closed in the meanwhile and no other context ever loads the extension. - */ - public RootCallTarget createCachedExternalFunWrapperCallTarget(Function rootNodeFunction, - Class klass, Enum signature, TruffleString name, - boolean doArgumentAndResultConversion, boolean isStatic) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, klass, signature, name, doArgumentAndResultConversion, isStatic); - } - public RootNode createCachedExternalFunWrapperRootNode(Function rootNodeFunction, Class klass, Enum signature, TruffleString name, boolean doArgumentAndResultConversion, boolean isStatic) { @@ -1251,18 +1226,10 @@ public RootNode createStructSeqIndexedMemberAccessCachedRootNode(Function rootNodeFunction, int memberIndex) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, StructSequence.class, memberIndex); - } - public RootNode createCachedPropAccessRootNode(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, name, type, offset); } - public RootCallTarget createCachedPropAccessCallTarget(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, name, type, offset); - } - /** * Keys in any caches held by {@link PythonLanguage} must be context independent objects and * there must be either finite number of their instances, or if the key is a context independent From e75b194fca89884d67a099de8cbaa28abbf8b577 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 3 May 2026 19:51:22 +0200 Subject: [PATCH 07/26] Use cached root nodes in async releasers --- .../graal/python/builtins/objects/mmap/MMapBuiltins.java | 8 ++++---- .../builtins/objects/posix/ScandirIteratorBuiltins.java | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index b05ca02ab9..90ce7a6f89 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -136,7 +136,6 @@ import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; import com.oracle.graal.python.util.OverflowException; import com.oracle.graal.python.util.PythonUtils; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.ThreadLocalAction.Access; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Bind; @@ -961,8 +960,9 @@ public void execute(PythonContext context, Access access) { return; } PythonLanguage language = context.getLanguage(); - CallTarget callTarget = language.createCachedCallTarget(MMapBuiltins.ReleaseCallback.ReleaserRootNode::new, MMapBuiltins.ReleaseCallback.ReleaserRootNode.class); - callTarget.call(ref); + ReleaserRootNode rootNode = (ReleaserRootNode) language.createCachedRootNode(MMapBuiltins.ReleaseCallback.ReleaserRootNode::new, + MMapBuiltins.ReleaseCallback.ReleaserRootNode.class); + rootNode.getCallTarget().call(ref); } private static class ReleaserRootNode extends RootNode { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java index 275519195b..532e7db8c5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -65,7 +65,6 @@ import com.oracle.graal.python.runtime.PosixSupportLibrary.PosixException; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.object.PFactory; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.ThreadLocalAction.Access; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Bind; @@ -170,8 +169,8 @@ public void execute(PythonContext context, Access access) { return; } PythonLanguage language = context.getLanguage(); - CallTarget callTarget = language.createCachedCallTarget(ReleaserRootNode::new, ReleaserRootNode.class); - callTarget.call(ref); + ReleaserRootNode rootNode = (ReleaserRootNode) language.createCachedRootNode(ReleaserRootNode::new, ReleaserRootNode.class); + rootNode.getCallTarget().call(ref); } private static class ReleaserRootNode extends RootNode { From e2ec9749b525fcad2fdd90c46949911271843acd Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 3 May 2026 22:07:12 +0200 Subject: [PATCH 08/26] Use cached root nodes for atexit hooks --- .../builtins/modules/AtexitModuleBuiltins.java | 7 +++---- .../oracle/graal/python/runtime/PythonContext.java | 13 +++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java index 16003763d2..7135fbc3d8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -66,7 +66,6 @@ import com.oracle.graal.python.runtime.exception.ExceptionUtils; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; @@ -135,8 +134,8 @@ private static void handleException(PythonContext context, PException e) { @Specialization static Object register(Object callable, Object[] arguments, PKeyword[] keywords) { PythonContext context = PythonContext.get(null); - RootCallTarget callTarget = context.getLanguage().createCachedCallTarget(AtExitRootNode::new, AtExitRootNode.class); - context.registerAtexitHook(callable, arguments, keywords, callTarget); + RootNode rootNode = context.getLanguage().createCachedRootNode(AtExitRootNode::new, AtExitRootNode.class); + context.registerAtexitHook(callable, arguments, keywords, rootNode); return callable; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 5f8d75d561..0ed9c6099d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -211,6 +211,7 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.api.strings.TruffleString.Encoding; @@ -683,13 +684,13 @@ private static final class AtExitHook { final Object callable; final Object[] arguments; final PKeyword[] keywords; - final CallTarget ct; + final RootNode rootNode; - AtExitHook(Object callable, Object[] arguments, PKeyword[] keywords, CallTarget ct) { + AtExitHook(Object callable, Object[] arguments, PKeyword[] keywords, RootNode rootNode) { this.callable = callable; this.arguments = arguments; this.keywords = keywords; - this.ct = ct; + this.rootNode = rootNode; } } @@ -2129,8 +2130,8 @@ public void registerAtexitHook(ShutdownHook shutdownHook) { } @TruffleBoundary - public void registerAtexitHook(Object callable, Object[] arguments, PKeyword[] keywords, CallTarget ct) { - atExitHooks.add(new AtExitHook(callable, arguments, keywords, ct)); + public void registerAtexitHook(Object callable, Object[] arguments, PKeyword[] keywords, RootNode rootNode) { + atExitHooks.add(new AtExitHook(callable, arguments, keywords, rootNode)); } @TruffleBoundary @@ -2245,7 +2246,7 @@ public void runAtexitHooks() { for (int i = atExitHooks.size() - 1; i >= 0; i--) { AtExitHook hook = atExitHooks.get(i); try { - hook.ct.call(hook.callable, hook.arguments, hook.keywords); + hook.rootNode.getCallTarget().call(hook.callable, hook.arguments, hook.keywords); } catch (PException e) { lastException = e; } From c96987c4aea8f941d88c646d165dc41848c4a8f1 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 3 May 2026 22:07:37 +0200 Subject: [PATCH 09/26] Remove dead generic calltarget cache APIs --- .../oracle/graal/python/PythonLanguage.java | 118 +----------------- 1 file changed, 1 insertion(+), 117 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index dae9c29f0b..b6e35ee2d7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -314,20 +314,11 @@ public boolean isSingleContext() { public final Assumption noInteropTypeRegisteredAssumption = Truffle.getRuntime().createAssumption("No class for interop registered"); /** - * Call targets that are populated during native-image build time and then only read at image + * Root nodes that are populated during native-image build time and then only read at image * runtime. Using {@link EconomicMap} avoids embedding a large number of * {@link java.util.concurrent.ConcurrentHashMap.Node} objects into the image heap. */ - private final EconomicMap imageBuildtimeCachedCallTargets = ImageInfo.inImageCode() ? EconomicMap.create() : null; - /** - * Root nodes that are populated during native-image build time and then only read at image - * runtime. - */ private final EconomicMap imageBuildtimeCachedRootNodes = ImageInfo.inImageCode() ? EconomicMap.create() : null; - /** - * Call targets added after image startup, or all cached call targets when running on the JVM. - */ - private final ConcurrentHashMap runtimeCachedCallTargets = new ConcurrentHashMap<>(); /** * Root nodes added after image startup, or all cached root nodes when running on the JVM. */ @@ -1114,45 +1105,16 @@ public void setCapiCallTarget(int index, RootCallTarget ct) { capiCallTargets[index] = ct; } - /** - * Caches call target that wraps a node that is not parametrized, i.e., has only a parameterless - * ctor and all its instances implement the same logic. Parametrized nodes must include the - * parameters that alter their behavior as part of the cache key. - */ - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class key) { - // It's complicated with RootNodes, but regular nodes should have only parameterless ctor to - // be appropriate keys for the cache - assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length <= 1; - assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length == 0 || key.getConstructors()[0].getParameterCount() == 0; - return createCachedCallTargetUnsafe(rootNodeFunction, key, true); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class key) { assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length <= 1; assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length == 0 || key.getConstructors()[0].getParameterCount() == 0; return createCachedRootNodeUnsafe(rootNodeFunction, key, true); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Enum key) { - return createCachedCallTargetUnsafe(rootNodeFunction, key, true); - } - - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, int key) { - return createCachedCallTargetUnsafe(rootNodeFunction, key, true); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Enum key) { return createCachedRootNodeUnsafe(rootNodeFunction, key, true); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, String key) { - // for builtins: name is needed to distinguish builtins that share the same underlying node - // in general: a String may be parameter of the node wrapped in the root node or the root - // node itself, there must be finite number of strings that can appear here (i.e., must not - // be dynamically generated unless their number is bounded). - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, String key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } @@ -1163,46 +1125,22 @@ public RootNode initBuiltinRootNode(Function rootNodeF return createCachedRootNodeUnsafe(rootNodeFunction, false, nodeClass, key); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, TruffleString key) { - // See the String overload - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, TruffleString key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass, int key) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass, key); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, int key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { - // for slot call targets and wrappers: the root node may be wrapping a helper wrapper node - // implementing the slot wrapper logic and the bare slot node itself - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, name); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, name); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { - // for slot wrappers: the type is used for validation of "self" type - return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name); - } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name); } - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, CodeUnit key) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, key); - } - public RootNode createCachedRootNode(Function rootNodeFunction, CodeUnit key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, key); } @@ -1213,15 +1151,6 @@ public RootNode createCachedExternalFunWrapperRootNode(Function rootNodeFunction, Enum signature, TruffleString name, - boolean doArgumentAndResultConversion) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, signature, name, doArgumentAndResultConversion); - } - - public RootCallTarget createCachedCallTarget(Function rootNodeFunction, Enum signature, TruffleString name) { - return createCachedCallTargetUnsafe(rootNodeFunction, true, signature, name); - } - public RootNode createStructSeqIndexedMemberAccessCachedRootNode(Function rootNodeFunction, int memberIndex) { return createCachedRootNodeUnsafe(rootNodeFunction, true, StructSequence.class, memberIndex); } @@ -1230,25 +1159,6 @@ public RootNode createCachedPropAccessRootNode(Function - * To avoid memory leaks, all key types must be known to have finite number of possible - * instances. Public methods for adding to the cache must take concrete key type(s) so that all - * possible cache keys are explicit and documented. - */ - private RootCallTarget createCachedCallTargetUnsafe(Function rootNodeFunction, Object key, boolean cacheInSingleContext) { - CompilerAsserts.neverPartOfCompilation(); - if (cacheInSingleContext || !singleContext) { - return getOrCreateCachedCallTarget(rootNodeFunction, key); - } else { - return PythonUtils.getOrCreateCallTarget(rootNodeFunction.apply(this)); - } - } - private RootNode createCachedRootNodeUnsafe(Function rootNodeFunction, Object key, boolean cacheInSingleContext) { CompilerAsserts.neverPartOfCompilation(); if (cacheInSingleContext || !singleContext) { @@ -1258,36 +1168,10 @@ private RootNode createCachedRootNodeUnsafe(Function r } } - private RootCallTarget createCachedCallTargetUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { - return createCachedCallTargetUnsafe(rootNodeFunction, Arrays.asList(cacheKeys), cacheInSingleContext); - } - private RootNode createCachedRootNodeUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { return createCachedRootNodeUnsafe(rootNodeFunction, Arrays.asList(cacheKeys), cacheInSingleContext); } - private RootCallTarget getOrCreateCachedCallTarget(Function rootNodeFunction, Object key) { - CompilerAsserts.neverPartOfCompilation(); - if (ImageInfo.inImageRuntimeCode()) { - RootCallTarget preinitialized = imageBuildtimeCachedCallTargets.get(key); - if (preinitialized != null) { - return preinitialized; - } - return runtimeCachedCallTargets.computeIfAbsent(key, k -> PythonUtils.getOrCreateCallTarget(rootNodeFunction.apply(this))); - } - if (ImageInfo.inImageBuildtimeCode()) { - synchronized (imageBuildtimeCachedCallTargets) { - RootCallTarget cached = imageBuildtimeCachedCallTargets.get(key); - if (cached == null) { - cached = PythonUtils.getOrCreateCallTarget(rootNodeFunction.apply(this)); - imageBuildtimeCachedCallTargets.put(key, cached); - } - return cached; - } - } - return runtimeCachedCallTargets.computeIfAbsent(key, k -> PythonUtils.getOrCreateCallTarget(rootNodeFunction.apply(this))); - } - private RootNode getOrCreateCachedRootNode(Function rootNodeFunction, Object key) { CompilerAsserts.neverPartOfCompilation(); if (ImageInfo.inImageRuntimeCode()) { From 5a04cd21a5bb1c46d509f2038a7944db055202b8 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 4 May 2026 10:05:18 +0200 Subject: [PATCH 10/26] Remove dead RootCallTarget helper overloads --- .../objects/function/PBuiltinFunction.java | 5 ----- .../python/builtins/objects/type/TypeNodes.java | 8 -------- .../com/oracle/graal/python/util/PythonUtils.java | 14 -------------- 3 files changed, 27 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index 96b3f2f15a..fdc7d07a60 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -255,11 +255,6 @@ public boolean needsDeclaringType() { return (flags & CExtContext.METH_METHOD) != 0; } - @TruffleBoundary - public static int getFlags(Builtin builtin, RootCallTarget callTarget) { - return getFlags(builtin, ((PRootNode) callTarget.getRootNode()).getSignature()); - } - @TruffleBoundary public static int getFlags(Builtin builtin, Signature signature) { if (builtin == null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 1ed752fa93..bedb57c816 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -228,7 +228,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Exclusive; @@ -2344,13 +2343,6 @@ private static void addWeakrefDescrAttribute(PythonClass pythonClass, PythonLang } } - private static void setAttribute(TruffleString name, Builtin builtin, RootCallTarget callTarget, PythonClass pythonClass, PythonLanguage language) { - int flags = PBuiltinFunction.getFlags(builtin, callTarget); - PBuiltinFunction function = PFactory.createBuiltinFunction(language, name, pythonClass, 1, flags, callTarget); - GetSetDescriptor desc = PFactory.createGetSetDescriptor(language, function, function, name, pythonClass, true); - pythonClass.setAttribute(name, desc); - } - private static void setAttribute(TruffleString name, Builtin builtin, BuiltinFunctionRootNode rootNode, PythonClass pythonClass, PythonLanguage language) { int flags = PBuiltinFunction.getFlags(builtin, rootNode.getSignature()); PBuiltinFunction function = PFactory.createBuiltinFunction(language, name, pythonClass, 1, flags, rootNode, false); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java index eeb4f6735a..fdcf7a70f3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java @@ -762,20 +762,6 @@ public static PBuiltinFunction createMethod(PythonLanguage language, Object klas return createMethod(klass, builtin, rootNode, type, numDefaults); } - @TruffleBoundary - public static PBuiltinFunction createMethod(Object klass, Builtin builtin, RootCallTarget callTarget, Object type, int numDefaults) { - RootNode rootNode = callTarget.getRootNode(); - assert rootNode instanceof BuiltinFunctionRootNode : String.format("root: %s, builtin: %s, klass: %s", rootNode, builtin, klass); - assert ((BuiltinFunctionRootNode) rootNode).getBuiltin() == builtin : String.format("%s != %s, klass: %s", ((BuiltinFunctionRootNode) rootNode).getBuiltin(), builtin, klass); - int flags = PBuiltinFunction.getFlags(builtin, callTarget); - TruffleString name = toInternedTruffleStringUncached(builtin.name()); - PBuiltinFunction function = PFactory.createBuiltinFunction(PythonLanguage.get(null), name, type, numDefaults, flags, callTarget); - if (klass != null) { - WriteAttributeToObjectNode.getUncached().execute(klass, name, function); - } - return function; - } - @TruffleBoundary public static PBuiltinFunction createMethod(Object klass, Builtin builtin, BuiltinFunctionRootNode rootNode, Object type, int numDefaults) { assert rootNode.getBuiltin() == builtin : String.format("%s != %s, klass: %s", rootNode.getBuiltin(), builtin, klass); From d879da66ce5e153b32f3f7d026fb87718c0e602b Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 4 May 2026 14:18:57 +0200 Subject: [PATCH 11/26] Fix instrumented usage of manual DSL root nodes --- .../oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java index 1d9e7c6248..af53f81826 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java @@ -2921,6 +2921,7 @@ public void materializeContainedFunctionsForInstrumentation(Set PBytecodeRootNode.createMaybeGenerator(language, codeUnit, getSource(), isInternal()), codeUnit); + rootNode.getCallTarget(); // make sure the calltarget is initialized if (rootNode instanceof PBytecodeGeneratorFunctionRootNode) { rootNode = ((PBytecodeGeneratorFunctionRootNode) rootNode).getBytecodeRootNode(); } From 11591e8e014cbc57e24f71cb3c5d4f4df6e9e599 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 5 May 2026 11:40:43 +0200 Subject: [PATCH 12/26] Materialize lazy DSL function roots for debugging --- ...strumentationMaterializationForwarder.java | 92 +++++++++++++++++++ .../bytecode_dsl/PBytecodeDSLRootNode.java | 26 ++++++ .../exception/TopLevelExceptionHandler.java | 3 + 3 files changed, 121 insertions(+) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java new file mode 100644 index 0000000000..01cc5386f4 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 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 + * + * 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. + */ +package com.oracle.graal.python.nodes.bytecode_dsl; + +import java.util.Set; + +import com.oracle.truffle.api.instrumentation.InstrumentableNode; +import com.oracle.truffle.api.instrumentation.ProbeNode; +import com.oracle.truffle.api.instrumentation.Tag; +import com.oracle.truffle.api.nodes.Node; + +class InstrumentationMaterializationForwarder extends Node implements InstrumentableNode { + private final PBytecodeDSLRootNode rootNode; + + InstrumentationMaterializationForwarder(PBytecodeDSLRootNode rootNode) { + this.rootNode = rootNode; + } + + @Override + public boolean isInstrumentable() { + return true; + } + + @Override + public WrapperNode createWrapper(ProbeNode probe) { + return new Wrapper(this, probe); + } + + @Override + public InstrumentableNode materializeInstrumentableNodes(Set> materializedTags) { + rootNode.materializeInstrumentableNodesForInstrumentation(materializedTags); + return this; + } + + private static class Wrapper extends Node implements WrapperNode { + @Child private Node delegateNode; + @Child private ProbeNode probeNode; + + Wrapper(Node delegateNode, ProbeNode probeNode) { + this.delegateNode = delegateNode; + this.probeNode = probeNode; + } + + @Override + public Node getDelegateNode() { + return delegateNode; + } + + @Override + public ProbeNode getProbeNode() { + return probeNode; + } + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java index bca9133a6c..d72925cf60 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java @@ -59,6 +59,7 @@ import java.math.BigInteger; import java.util.Iterator; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import com.oracle.graal.python.PythonLanguage; @@ -300,6 +301,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; @@ -487,6 +489,30 @@ public final void triggerDeferredDeprecationWarnings() { } } + @TruffleBoundary + @SuppressWarnings({"rawtypes", "unchecked"}) + public void materializeInstrumentableNodesForInstrumentation(Set> materializedTags) { + prepareForInstrumentation((Set) materializedTags); + materializeContainedFunctionsForInstrumentation(materializedTags); + } + + @TruffleBoundary + private void materializeContainedFunctionsForInstrumentation(Set> materializedTags) { + Object[] constants = co.constants; + for (Object constant : constants) { + if (constant instanceof BytecodeDSLCodeUnit codeUnit) { + PythonLanguage language = getLanguage(); + PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, getSource()), codeUnit); + rootNode.getCallTarget(); + rootNode.materializeInstrumentableNodesForInstrumentation(materializedTags); + } + } + } + + public Node createInstrumentationMaterializationForwarder() { + return new InstrumentationMaterializationForwarder(this); + } + @Override public String toString() { return ""; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java index 5e54db44d2..a2278aeec6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java @@ -61,6 +61,7 @@ import com.oracle.graal.python.lib.PyObjectStrAsObjectNode; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode; +import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode; import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.object.GetClassNode; import com.oracle.graal.python.nodes.object.GetClassNode.GetPythonObjectClassNode; @@ -119,6 +120,8 @@ public TopLevelExceptionHandler(PythonLanguage language, RootNode child, Source this.source = source; if (child instanceof PBytecodeRootNode) { instrumentationForwarder = ((PBytecodeRootNode) child).createInstrumentationMaterializationForwarder(); + } else if (child instanceof PBytecodeDSLRootNode) { + instrumentationForwarder = ((PBytecodeDSLRootNode) child).createInstrumentationMaterializationForwarder(); } this.newGlobals = source.getOptions(language).get(PythonSourceOptions.NewGlobals); } From 2bfdefdcc541ef293a1279568101300d353196e5 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 May 2026 15:39:54 +0200 Subject: [PATCH 13/26] Revert "Materialize lazy DSL function roots for debugging" This reverts commit 8700c1df436249716192dbce2a8ab16d7fed7a59. --- ...strumentationMaterializationForwarder.java | 92 ------------------- .../bytecode_dsl/PBytecodeDSLRootNode.java | 26 ------ .../exception/TopLevelExceptionHandler.java | 3 - 3 files changed, 121 deletions(-) delete mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java deleted file mode 100644 index 01cc5386f4..0000000000 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/InstrumentationMaterializationForwarder.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 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 - * - * 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. - */ -package com.oracle.graal.python.nodes.bytecode_dsl; - -import java.util.Set; - -import com.oracle.truffle.api.instrumentation.InstrumentableNode; -import com.oracle.truffle.api.instrumentation.ProbeNode; -import com.oracle.truffle.api.instrumentation.Tag; -import com.oracle.truffle.api.nodes.Node; - -class InstrumentationMaterializationForwarder extends Node implements InstrumentableNode { - private final PBytecodeDSLRootNode rootNode; - - InstrumentationMaterializationForwarder(PBytecodeDSLRootNode rootNode) { - this.rootNode = rootNode; - } - - @Override - public boolean isInstrumentable() { - return true; - } - - @Override - public WrapperNode createWrapper(ProbeNode probe) { - return new Wrapper(this, probe); - } - - @Override - public InstrumentableNode materializeInstrumentableNodes(Set> materializedTags) { - rootNode.materializeInstrumentableNodesForInstrumentation(materializedTags); - return this; - } - - private static class Wrapper extends Node implements WrapperNode { - @Child private Node delegateNode; - @Child private ProbeNode probeNode; - - Wrapper(Node delegateNode, ProbeNode probeNode) { - this.delegateNode = delegateNode; - this.probeNode = probeNode; - } - - @Override - public Node getDelegateNode() { - return delegateNode; - } - - @Override - public ProbeNode getProbeNode() { - return probeNode; - } - } -} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java index d72925cf60..bca9133a6c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java @@ -59,7 +59,6 @@ import java.math.BigInteger; import java.util.Iterator; -import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import com.oracle.graal.python.PythonLanguage; @@ -301,7 +300,6 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; @@ -489,30 +487,6 @@ public final void triggerDeferredDeprecationWarnings() { } } - @TruffleBoundary - @SuppressWarnings({"rawtypes", "unchecked"}) - public void materializeInstrumentableNodesForInstrumentation(Set> materializedTags) { - prepareForInstrumentation((Set) materializedTags); - materializeContainedFunctionsForInstrumentation(materializedTags); - } - - @TruffleBoundary - private void materializeContainedFunctionsForInstrumentation(Set> materializedTags) { - Object[] constants = co.constants; - for (Object constant : constants) { - if (constant instanceof BytecodeDSLCodeUnit codeUnit) { - PythonLanguage language = getLanguage(); - PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, getSource()), codeUnit); - rootNode.getCallTarget(); - rootNode.materializeInstrumentableNodesForInstrumentation(materializedTags); - } - } - } - - public Node createInstrumentationMaterializationForwarder() { - return new InstrumentationMaterializationForwarder(this); - } - @Override public String toString() { return ""; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java index a2278aeec6..5e54db44d2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java @@ -61,7 +61,6 @@ import com.oracle.graal.python.lib.PyObjectStrAsObjectNode; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode; -import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode; import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.object.GetClassNode; import com.oracle.graal.python.nodes.object.GetClassNode.GetPythonObjectClassNode; @@ -120,8 +119,6 @@ public TopLevelExceptionHandler(PythonLanguage language, RootNode child, Source this.source = source; if (child instanceof PBytecodeRootNode) { instrumentationForwarder = ((PBytecodeRootNode) child).createInstrumentationMaterializationForwarder(); - } else if (child instanceof PBytecodeDSLRootNode) { - instrumentationForwarder = ((PBytecodeDSLRootNode) child).createInstrumentationMaterializationForwarder(); } this.newGlobals = source.getOptions(language).get(PythonSourceOptions.NewGlobals); } From 3a075abad35e6153492be819f0ce8c4352fa9cdd Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 May 2026 15:47:51 +0200 Subject: [PATCH 14/26] Use instrumentation prep for lazy DSL roots --- .../nodes/bytecode_dsl/PBytecodeDSLRootNode.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java index bca9133a6c..214874f60e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java @@ -59,6 +59,7 @@ import java.math.BigInteger; import java.util.Iterator; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import com.oracle.graal.python.PythonLanguage; @@ -444,6 +445,19 @@ public static void updateAllToTracingConfig(PythonLanguage language) { PBytecodeDSLRootNodeGen.BYTECODE.update(language, TRACE_AND_PROFILE_CONFIG); } + @Override + @TruffleBoundary + protected void prepareForInstrumentation(Set> materializedTags) { + super.prepareForInstrumentation(materializedTags); + PythonLanguage language = getLanguage(); + for (Object constant : co.constants) { + if (constant instanceof BytecodeDSLCodeUnit codeUnit) { + PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, getSource()), codeUnit); + rootNode.getCallTarget(); + } + } + } + public final PythonLanguage getLanguage() { return getLanguage(PythonLanguage.class); } From 253fc5ad452f37e883d92e7d52ba8022423b32a6 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 11 May 2026 15:01:23 +0200 Subject: [PATCH 15/26] Get rid of temporary call target initialization counter used for measurements --- .../runtime/LazyBuiltinCallTargetTests.java | 108 ------------------ .../graal/python/builtins/PythonBuiltins.java | 2 +- .../cext/capi/CApiMemberAccessNodes.java | 8 +- .../python/builtins/objects/code/PCode.java | 75 ++++-------- .../objects/function/PBuiltinFunction.java | 57 +-------- .../objects/tuple/StructSequence.java | 2 +- .../builtins/objects/type/TypeNodes.java | 2 +- .../graal/python/runtime/object/PFactory.java | 11 +- .../oracle/graal/python/util/PythonUtils.java | 2 +- 9 files changed, 36 insertions(+), 231 deletions(-) delete mode 100644 graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java diff --git a/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java b/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java deleted file mode 100644 index 0a0a7b5454..0000000000 --- a/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/LazyBuiltinCallTargetTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 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 - * - * 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. - */ -package com.oracle.graal.python.test.runtime; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Engine; -import org.junit.Test; - -import com.oracle.graal.python.builtins.objects.code.PCode; -import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; - -public class LazyBuiltinCallTargetTests { - - @Test - public void builtinCallTargetsRemainLazyAfterStartup() { - int totalBefore = PBuiltinFunction.getTrackedBuiltinFunctionCount(); - int callTargetsBefore = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); - try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); - Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { - assertEquals(0, context.eval("python", "0").asInt()); - } - int totalDelta = PBuiltinFunction.getTrackedBuiltinFunctionCount() - totalBefore; - int callTargetDelta = PBuiltinFunction.getTrackedBuiltinCallTargetCount() - callTargetsBefore; - assertTrue(String.format("expected tracked builtin functions to be registered during startup, totalDelta=%d", totalDelta), totalDelta > 0); - assertTrue(String.format("expected fewer builtin call targets than builtin functions to be initialized during startup, totalDelta=%d callTargetDelta=%d", totalDelta, callTargetDelta), - callTargetDelta < totalDelta); - } - - @Test - public void builtinCallTargetsInitializeOnFirstUse() { - try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); - Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { - assertEquals(0, context.eval("python", "0").asInt()); - int beforeCalls = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); - assertEquals(0, context.eval("python", "abs(-42)\n[].append(1)\n0").asInt()); - int afterCalls = PBuiltinFunction.getTrackedBuiltinCallTargetCount(); - assertTrue(String.format("expected builtin calls to initialize at least one lazy call target, before=%d after=%d", beforeCalls, afterCalls), afterCalls > beforeCalls); - } - } - - @Test - public void codeCallTargetsRemainLazyAfterFunctionDefinition() { - int totalBefore = PCode.getTrackedCodeCount(); - int callTargetsBefore = PCode.getTrackedCodeCallTargetCount(); - try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); - Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { - assertEquals(0, context.eval("python", "def f():\n return 1\n0").asInt()); - } - int totalDelta = PCode.getTrackedCodeCount() - totalBefore; - int callTargetDelta = PCode.getTrackedCodeCallTargetCount() - callTargetsBefore; - assertTrue(String.format("expected tracked child code objects to be created, totalDelta=%d", totalDelta), totalDelta > 0); - assertTrue(String.format("expected fewer code call targets than tracked code objects after definition, totalDelta=%d callTargetDelta=%d", totalDelta, callTargetDelta), - callTargetDelta < totalDelta); - } - - @Test - public void codeCallTargetsInitializeOnFirstInvocation() { - try (Engine engine = Engine.newBuilder("python").allowExperimentalOptions(true).build(); - Context context = Context.newBuilder("python").engine(engine).allowExperimentalOptions(true).allowAllAccess(true).build()) { - assertEquals(0, context.eval("python", "def f():\n return 1\n0").asInt()); - int beforeCalls = PCode.getTrackedCodeCallTargetCount(); - assertEquals(1, context.eval("python", "f()").asInt()); - int afterCalls = PCode.getTrackedCodeCallTargetCount(); - assertTrue(String.format("expected code invocation to initialize at least one lazy call target, before=%d after=%d", beforeCalls, afterCalls), afterCalls > beforeCalls); - } - } -} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java index 7ef1377441..cd31e8e4a0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java @@ -113,7 +113,7 @@ public void initialize(Python3Core core) { factory.getNodeClass(), builtin.name()); Signature signature = rootNode.getSignature(); int flags = PBuiltinFunction.getFlags(builtin, signature); - PBuiltinFunction function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, rootNode, true); + PBuiltinFunction function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, rootNode); function.setAttribute(T___DOC__, builtinDoc); BoundBuiltinCallable callable = function; if (builtin.isGetter() || builtin.isSetter()) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java index 46529dbfe9..37cc05d45a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java @@ -254,7 +254,7 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Ob l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadMemberNodeGen.create(type, offset, asPythonObjectNode)), true), ReadMemberNode.class, BUILTIN.name(), type, offset); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); - return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode, false); + return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode); } } @@ -280,7 +280,7 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Tr l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadOnlyMemberNodeGen.create(propertyName)), true), ReadOnlyMemberNode.class, BUILTIN.name()); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); - return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode, false); + return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode); } } @@ -304,7 +304,7 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Tr l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(BadMemberDescrNodeGen.create()), true), BadMemberDescrNode.class, BUILTIN.name()); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); - return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode, false); + return PFactory.createBuiltinFunction(language, propertyName, null, 0, flags, rootNode); } } @@ -603,7 +603,7 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Ob l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(WriteMemberNodeGen.create(type, offset)), true), WriteMemberNode.class, BUILTIN.name(), type, offset); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); - return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode, false); + return PFactory.createBuiltinFunction(language, propertyName, owner, 0, flags, rootNode); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 15feae7b7d..df76ca6ebf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -46,7 +46,6 @@ import java.math.BigInteger; import java.util.Arrays; -import java.util.concurrent.atomic.AtomicInteger; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.bytes.PBytes; @@ -88,9 +87,6 @@ @ExportLibrary(InteropLibrary.class) public final class PCode extends PythonBuiltinObject { - private static final AtomicInteger TRACKED_CODE_COUNT = new AtomicInteger(); - private static final AtomicInteger TRACKED_CODE_CALL_TARGET_COUNT = new AtomicInteger(); - public static final int CO_OPTIMIZED = 0x1; public static final int CO_NEWLOCALS = 0x2; public static final int CO_VARARGS = 0x4; @@ -105,10 +101,7 @@ public final class PCode extends PythonBuiltinObject { public static final int CO_GRAALPYHON_MODULE = 0x1000; private final RootNode rootNode; - private volatile RootCallTarget callTarget; private final Signature signature; - private final boolean trackCallTargetInitialization; - private volatile boolean callTargetCounted; // number of local variables private int nlocals = -1; @@ -149,10 +142,7 @@ public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget) { public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, TruffleString filename) { super(cls, instanceShape); this.rootNode = callTarget.getRootNode(); - this.callTarget = callTarget; this.signature = Signature.fromCallTarget(callTarget); - this.trackCallTargetInitialization = false; - this.callTargetCounted = true; this.filename = filename; } @@ -196,10 +186,7 @@ public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signatu this.freevars = freevars; this.cellvars = cellvars; this.rootNode = callTarget.getRootNode(); - this.callTarget = callTarget; this.signature = signature; - this.trackCallTargetInitialization = false; - this.callTargetCounted = true; assert signature != null; } @@ -207,9 +194,7 @@ public PCode(Object cls, Shape instanceShape, PRootNode rootNode, TruffleString super(cls, instanceShape); this.rootNode = rootNode; this.signature = rootNode.getSignature(); - this.trackCallTargetInitialization = true; this.filename = filename; - TRACKED_CODE_COUNT.incrementAndGet(); } public PCode(Object cls, Shape instanceShape, PRootNode rootNode, int flags, int firstlineno, byte[] linetable, TruffleString filename) { @@ -252,8 +237,6 @@ public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature sign this.cellvars = cellvars; this.rootNode = rootNode; this.signature = signature; - this.trackCallTargetInitialization = true; - TRACKED_CODE_COUNT.incrementAndGet(); assert signature != null; } @@ -376,8 +359,8 @@ private static TruffleString[] extractNames(RootNode node) { return EMPTY_TRUFFLESTRING_ARRAY; } - private static RootNode rootNodeForExtraction(RootNode rootNode) { - rootNode = PythonLanguage.unwrapRootNode(rootNode); + private static RootNode rootNodeForExtraction(RootNode rootNodeArg) { + RootNode rootNode = PythonLanguage.unwrapRootNode(rootNodeArg); if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER) { return PGenerator.unwrapContinuationRoot(rootNode); } else { @@ -436,9 +419,8 @@ public TruffleString[] getCellVars() { } @TruffleBoundary - public void fixCoFilename(TruffleString filename) { - filename = PythonUtils.internString(filename); - this.filename = filename; + public void fixCoFilename(TruffleString filenameArg) { + filename = PythonUtils.internString(filenameArg); /* * New code objects inherit the filename from parent, so no need to eagerly construct them * here @@ -538,9 +520,9 @@ public TruffleString[] getVarnames() { } public byte[] getCodestring(Node node) { - RootNode rootNode = getRootNode(); - if (rootNode instanceof PRootNode) { - return ((PRootNode) rootNode).getCode(node); + RootNode rN = getRootNode(); + if (rN instanceof PRootNode) { + return ((PRootNode) rN).getCode(node); } else { return PythonUtils.EMPTY_BYTE_ARRAY; } @@ -572,8 +554,8 @@ public PCode getOrCreateChildCode(int index, BytecodeDSLCodeUnit codeUnit) { private PCode createCode(BytecodeDSLCodeUnit codeUnit) { PBytecodeDSLRootNode outerRootNode = (PBytecodeDSLRootNode) getRootNodeForExtraction(); PythonLanguage language = outerRootNode.getLanguage(); - PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); - return PFactory.createCode(language, rootNode, rootNode.getSignature(), codeUnit, getFilename()); + PBytecodeDSLRootNode rN = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); + return PFactory.createCode(language, rN, rN.getSignature(), codeUnit, getFilename()); } public PCode getOrCreateChildCode(int index, BytecodeCodeUnit codeUnit) { @@ -592,11 +574,11 @@ private PCode createCode(BytecodeCodeUnit codeUnit) { PythonLanguage language = outerRootNode.getLanguage(); PRootNode executableRootNode = (PRootNode) language.createCachedRootNode( l -> PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getSource(), outerRootNode.isInternal()), codeUnit); - RootNode rootNode = executableRootNode; + RootNode rN = executableRootNode; if (executableRootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { - rootNode = generatorRoot.getBytecodeRootNode(); + rN = generatorRoot.getBytecodeRootNode(); } - return PFactory.createCode(language, executableRootNode, ((PBytecodeRootNode) rootNode).getSignature(), codeUnit, getFilename()); + return PFactory.createCode(language, executableRootNode, ((PBytecodeRootNode) rN).getSignature(), codeUnit, getFilename()); } @TruffleBoundary @@ -677,24 +659,7 @@ public Signature getSignature() { } public RootCallTarget getRootCallTarget() { - RootCallTarget ct = callTarget; - if (ct == null) { - ct = rootNode.getCallTarget(); - callTarget = ct; - if (trackCallTargetInitialization && !callTargetCounted) { - callTargetCounted = true; - TRACKED_CODE_CALL_TARGET_COUNT.incrementAndGet(); - } - } - return ct; - } - - public static int getTrackedCodeCount() { - return TRACKED_CODE_COUNT.get(); - } - - public static int getTrackedCodeCallTargetCount() { - return TRACKED_CODE_CALL_TARGET_COUNT.get(); + return rootNode.getCallTarget(); } @ExportMessage @@ -745,15 +710,15 @@ public String toString() { @TruffleBoundary public String toDisassembledString(boolean quickened) { - RootNode rootNode = getRootCallTarget().getRootNode(); - if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER && rootNode instanceof PBytecodeDSLRootNode dslRoot) { + RootNode rN = getRootCallTarget().getRootNode(); + if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER && rN instanceof PBytecodeDSLRootNode dslRoot) { return dslRoot.getCodeUnit().toString(quickened, dslRoot); - } else if (rootNode instanceof PBytecodeGeneratorRootNode r) { - rootNode = r.getBytecodeRootNode(); - } else if (rootNode instanceof PBytecodeGeneratorFunctionRootNode r) { - rootNode = r.getBytecodeRootNode(); + } else if (rN instanceof PBytecodeGeneratorRootNode r) { + rN = r.getBytecodeRootNode(); + } else if (rN instanceof PBytecodeGeneratorFunctionRootNode r) { + rN = r.getBytecodeRootNode(); } - if (rootNode instanceof PBytecodeRootNode bytecodeRootNode) { + if (rN instanceof PBytecodeRootNode bytecodeRootNode) { return bytecodeRootNode.getCodeUnit().toString(quickened, bytecodeRootNode); } return J_EMPTY_STRING; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index fdc7d07a60..ec38840ff8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -29,7 +29,6 @@ import static com.oracle.graal.python.nodes.StringLiterals.T_DOT; import java.util.Arrays; -import java.util.concurrent.atomic.AtomicInteger; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.Builtin; @@ -72,48 +71,22 @@ */ @ExportLibrary(InteropLibrary.class) public final class PBuiltinFunction extends PythonBuiltinObject implements BoundBuiltinCallable { - private static final AtomicInteger TRACKED_BUILTIN_FUNCTION_COUNT = new AtomicInteger(); - private static final AtomicInteger TRACKED_BUILTIN_CALL_TARGET_COUNT = new AtomicInteger(); - private static final class Executable { private final RootNode functionRootNode; private final Signature signature; - private final boolean trackCallTargetInitialization; - private volatile RootCallTarget callTarget; - private volatile boolean callTargetCounted; - private Executable(RootCallTarget callTarget, boolean trackCallTargetInitialization) { + private Executable(RootCallTarget callTarget) { this.functionRootNode = callTarget.getRootNode(); this.signature = ((PRootNode) functionRootNode).getSignature(); - this.callTarget = callTarget; - this.trackCallTargetInitialization = trackCallTargetInitialization; - this.callTargetCounted = callTarget != null; - if (trackCallTargetInitialization) { - TRACKED_BUILTIN_FUNCTION_COUNT.incrementAndGet(); - TRACKED_BUILTIN_CALL_TARGET_COUNT.incrementAndGet(); - } } - private Executable(PRootNode rootNode, boolean trackCallTargetInitialization) { + private Executable(PRootNode rootNode) { this.functionRootNode = rootNode; this.signature = rootNode.getSignature(); - this.trackCallTargetInitialization = trackCallTargetInitialization; - if (trackCallTargetInitialization) { - TRACKED_BUILTIN_FUNCTION_COUNT.incrementAndGet(); - } } private synchronized RootCallTarget getCallTarget() { - RootCallTarget ct = callTarget; - if (ct == null) { - ct = functionRootNode.getCallTarget(); - callTarget = ct; - if (trackCallTargetInitialization && !callTargetCounted) { - callTargetCounted = true; - TRACKED_BUILTIN_CALL_TARGET_COUNT.incrementAndGet(); - } - } - return ct; + return functionRootNode.getCallTarget(); } private RootNode getFunctionRootNode() { @@ -165,31 +138,21 @@ private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget, false), slot, slotWrapper); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget), slot, slotWrapper); } public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget) { this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, callTarget, null, null); } - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, - boolean trackCallTargetInitialization) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget, trackCallTargetInitialization), null, null); - } - - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, - PRootNode rootNode, boolean trackCallTargetInitialization) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, trackCallTargetInitialization), null, null); - } - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PRootNode rootNode) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, false), null, null); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode), null, null); } public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode, false), slot, slotWrapper); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode), slot, slotWrapper); } public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PBuiltinFunction source, @@ -303,14 +266,6 @@ public boolean forceSplitDirectCalls() { return executable.forceSplitDirectCalls(); } - public static int getTrackedBuiltinFunctionCount() { - return TRACKED_BUILTIN_FUNCTION_COUNT.get(); - } - - public static int getTrackedBuiltinCallTargetCount() { - return TRACKED_BUILTIN_CALL_TARGET_COUNT.get(); - } - public TruffleString getName() { return name.getMaterialized(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java index 495cbc5e3c..f242808d09 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java @@ -224,7 +224,7 @@ private static void copyMethod(PythonLanguage language, PythonAbstractClass klas private static void createMember(PythonLanguage language, Object klass, TruffleString name, TruffleString doc, int idx) { GetStructMemberNode rootNode = (GetStructMemberNode) language.createStructSeqIndexedMemberAccessCachedRootNode((l) -> new GetStructMemberNode(l, idx), idx); - PBuiltinFunction getter = PFactory.createBuiltinFunction(language, name, klass, 0, 0, rootNode, false); + PBuiltinFunction getter = PFactory.createBuiltinFunction(language, name, klass, 0, 0, rootNode); GetSetDescriptor callable = PFactory.createGetSetDescriptor(language, getter, null, name, klass, false); if (doc != null) { callable.setAttribute(T___DOC__, doc); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index bedb57c816..944d872fc2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -2345,7 +2345,7 @@ private static void addWeakrefDescrAttribute(PythonClass pythonClass, PythonLang private static void setAttribute(TruffleString name, Builtin builtin, BuiltinFunctionRootNode rootNode, PythonClass pythonClass, PythonLanguage language) { int flags = PBuiltinFunction.getFlags(builtin, rootNode.getSignature()); - PBuiltinFunction function = PFactory.createBuiltinFunction(language, name, pythonClass, 1, flags, rootNode, false); + PBuiltinFunction function = PFactory.createBuiltinFunction(language, name, pythonClass, 1, flags, rootNode); GetSetDescriptor desc = PFactory.createGetSetDescriptor(language, function, function, name, pythonClass, true); pythonClass.setAttribute(name, desc); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 63fd97857f..0f9086d398 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -520,16 +520,9 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Tr PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget); } - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, RootCallTarget callTarget, - boolean trackCallTargetInitialization) { + public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode) { return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget, trackCallTargetInitialization); - } - - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode, - boolean trackCallTargetInitialization) { - return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, trackCallTargetInitialization); + PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode); } public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, RootCallTarget callTarget) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java index fdcf7a70f3..981c7240b8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java @@ -767,7 +767,7 @@ public static PBuiltinFunction createMethod(Object klass, Builtin builtin, Built assert rootNode.getBuiltin() == builtin : String.format("%s != %s, klass: %s", rootNode.getBuiltin(), builtin, klass); int flags = PBuiltinFunction.getFlags(builtin, rootNode.getSignature()); TruffleString name = toInternedTruffleStringUncached(builtin.name()); - PBuiltinFunction function = PFactory.createBuiltinFunction(PythonLanguage.get(null), name, type, numDefaults, flags, rootNode, false); + PBuiltinFunction function = PFactory.createBuiltinFunction(PythonLanguage.get(null), name, type, numDefaults, flags, rootNode); if (klass != null) { WriteAttributeToObjectNode.getUncached().execute(klass, name, function); } From 0ee3fa6d2705f41cf5dc77200104a362c09272f9 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 11 May 2026 15:33:42 +0200 Subject: [PATCH 16/26] Clean up dead code paths for functions and code from call targets --- .../python/builtins/objects/code/PCode.java | 38 +----------------- .../objects/function/PBuiltinFunction.java | 16 +------- .../graal/python/runtime/object/PFactory.java | 39 ------------------- 3 files changed, 2 insertions(+), 91 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index df76ca6ebf..21e2472985 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -160,48 +160,12 @@ public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signatu codeUnit.name, codeUnit.qualname, -1, codeUnit.srcOffsetTable); } - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { - this(cls, instanceShape, callTarget, signature, codeUnit.varnames.length, -1, -1, null, null, - null, null, null, filename, - codeUnit.name, codeUnit.qualname, -1, null); - } - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signature signature, int nlocals, int stacksize, int flags, Object[] constants, TruffleString[] names, TruffleString[] varnames, TruffleString[] freevars, TruffleString[] cellvars, TruffleString filename, TruffleString name, TruffleString qualname, int firstlineno, byte[] linetable) { - super(cls, instanceShape); - this.nlocals = nlocals; - this.stacksize = stacksize; - this.flags = flags; - this.constants = constants; - this.names = names; - this.varnames = varnames; - this.filename = filename; - this.name = name; - this.qualname = qualname; - this.firstlineno = firstlineno; - this.linetable = linetable; - this.freevars = freevars; - this.cellvars = cellvars; - this.rootNode = callTarget.getRootNode(); - this.signature = signature; - assert signature != null; - } - - public PCode(Object cls, Shape instanceShape, PRootNode rootNode, TruffleString filename) { - super(cls, instanceShape); - this.rootNode = rootNode; - this.signature = rootNode.getSignature(); - this.filename = filename; - } - - public PCode(Object cls, Shape instanceShape, PRootNode rootNode, int flags, int firstlineno, byte[] linetable, TruffleString filename) { - this(cls, instanceShape, rootNode, filename); - this.flags = flags; - this.firstlineno = firstlineno; - this.linetable = linetable; + this(cls, instanceShape, (PRootNode) callTarget.getRootNode(), signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); } public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index ec38840ff8..4c911dec7a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -75,17 +75,12 @@ private static final class Executable { private final RootNode functionRootNode; private final Signature signature; - private Executable(RootCallTarget callTarget) { - this.functionRootNode = callTarget.getRootNode(); - this.signature = ((PRootNode) functionRootNode).getSignature(); - } - private Executable(PRootNode rootNode) { this.functionRootNode = rootNode; this.signature = rootNode.getSignature(); } - private synchronized RootCallTarget getCallTarget() { + private RootCallTarget getCallTarget() { return functionRootNode.getCallTarget(); } @@ -136,15 +131,6 @@ private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString this.slotWrapper = slotWrapper; } - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget, - TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(callTarget), slot, slotWrapper); - } - - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, callTarget, null, null); - } - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PRootNode rootNode) { this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode), null, null); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 0f9086d398..66ac86497e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -515,36 +515,15 @@ public static PFunction createFunction(PythonLanguage language, TruffleString na return new PFunction(language, name, qualname, code, globals, defaultValues, kwDefaultValues, closure, codeStableAssumption); } - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, RootCallTarget callTarget) { - return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget); - } - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode) { return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode); } - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, RootCallTarget callTarget) { - return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, callTarget); - } - public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, PRootNode rootNode) { return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, rootNode); } - public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, RootCallTarget callTarget, TpSlot slot, - PExternalFunctionWrapper slotWrapper) { - return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, callTarget, slot, slotWrapper); - } - - public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, RootCallTarget callTarget, - TpSlot slot, PExternalFunctionWrapper slotWrapper) { - return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, defaults, kw, flags, - callTarget, slot, slotWrapper); - } - public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, @@ -557,12 +536,6 @@ public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, rootNode, slot, slotWrapper); } - public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object type, Object[] defaults, PKeyword[] kwdefaults, RootCallTarget callTarget, TpSlot slot) { - PBuiltinFunction func = createWrapperDescriptor(language, T___NEW__, type, defaults, kwdefaults, CExtContext.METH_VARARGS | CExtContext.METH_KEYWORDS, callTarget, slot, - PExternalFunctionWrapper.NEW); - return createBuiltinMethod(language, type, func); - } - public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object type, Object[] defaults, PKeyword[] kwdefaults, PRootNode rootNode, TpSlot slot) { PBuiltinFunction func = createWrapperDescriptor(language, T___NEW__, type, defaults, kwdefaults, CExtContext.METH_VARARGS | CExtContext.METH_KEYWORDS, rootNode, slot, PExternalFunctionWrapper.NEW); @@ -1108,18 +1081,10 @@ public static PCode createCode(PythonLanguage language, RootCallTarget ct, Truff return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, filename); } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, filename); - } - public static PCode createCode(PythonLanguage language, RootCallTarget ct, int flags, int firstlineno, byte[] linetable, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, flags, firstlineno, linetable, filename); } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, int flags, int firstlineno, byte[] linetable, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, flags, firstlineno, linetable, filename); - } - public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, codeUnit, filename); } @@ -1128,10 +1093,6 @@ public static PCode createCode(PythonLanguage language, PRootNode rootNode, Sign return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); } - public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, codeUnit, filename); - } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); } From ba2d06c95ab131206142cdc05128604124d8f214 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 11 May 2026 15:34:21 +0200 Subject: [PATCH 17/26] Get rid of separate call target cache on the language, caching only root nodes --- .../com/oracle/graal/python/PythonLanguage.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index b6e35ee2d7..b6c55fe2c0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -324,7 +324,6 @@ public boolean isSingleContext() { */ private final ConcurrentHashMap runtimeCachedRootNodes = new ConcurrentHashMap<>(); - @CompilationFinal(dimensions = 1) private final RootCallTarget[] builtinSlotsCallTargets; @CompilationFinal(dimensions = 1) private RootCallTarget[] capiCallTargets; @CompilationFinal(dimensions = 1) private final RootNode[] builtinSlotsRootNodes; @@ -389,7 +388,6 @@ public PythonLanguage() { if (PythonBuiltinClassType.PythonClass.getSlots() == null) { throw new IllegalStateException("Slots must be initialized in PythonBuiltinClassType static initializer"); } - builtinSlotsCallTargets = new RootCallTarget[TpSlot.getBuiltinsCallTargetsCount()]; builtinSlotsRootNodes = new RootNode[TpSlot.getBuiltinsCallTargetsCount()]; } @@ -1070,16 +1068,9 @@ private Shape createBuiltinShape(PythonBuiltinClassType type, int ordinal) { } public RootCallTarget getBuiltinSlotCallTarget(int index) { - RootCallTarget callTarget = builtinSlotsCallTargets[index]; - if (callTarget == null) { - RootNode rootNode = builtinSlotsRootNodes[index]; - if (rootNode != null) { - callTarget = rootNode.getCallTarget(); - VarHandle.storeStoreFence(); - builtinSlotsCallTargets[index] = callTarget; - } - } - return callTarget; + RootNode rootNode = builtinSlotsRootNodes[index]; + assert rootNode != null : index; + return rootNode.getCallTarget(); } public void setBuiltinSlotRootNode(int index, RootNode rootNode) { From 9d6fad395e175e485c34a6e1a5d850a8786338a6 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 11 May 2026 20:12:51 +0200 Subject: [PATCH 18/26] Remove temporary indirection in PBuiltinfunction --- .../objects/function/PBuiltinFunction.java | 55 +++++-------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index 4c911dec7a..488474270c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -71,40 +71,10 @@ */ @ExportLibrary(InteropLibrary.class) public final class PBuiltinFunction extends PythonBuiltinObject implements BoundBuiltinCallable { - private static final class Executable { - private final RootNode functionRootNode; - private final Signature signature; - - private Executable(PRootNode rootNode) { - this.functionRootNode = rootNode; - this.signature = rootNode.getSignature(); - } - - private RootCallTarget getCallTarget() { - return functionRootNode.getCallTarget(); - } - - private RootNode getFunctionRootNode() { - return functionRootNode; - } - - private NodeFactory getBuiltinNodeFactory() { - return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot ? builtinRoot.getFactory() : null; - } - - private boolean declaresExplicitSelf() { - return !(functionRootNode instanceof BuiltinFunctionRootNode builtinRoot) || builtinRoot.declaresExplicitSelf(); - } - - private boolean forceSplitDirectCalls() { - return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot && builtinRoot.getBuiltin().forceSplitDirectCalls(); - } - } - private final PString name; private final TruffleString qualname; private final Object enclosingType; - private final Executable executable; + private final RootNode functionRootNode; private final Signature signature; private final int flags; private final TpSlot slot; @@ -112,7 +82,8 @@ private boolean forceSplitDirectCalls() { @CompilationFinal(dimensions = 1) private final Object[] defaults; @CompilationFinal(dimensions = 1) private final PKeyword[] kwDefaults; - private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, Executable executable, + private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootNode functionRootNode, + Signature signature, TpSlot slot, PExternalFunctionWrapper slotWrapper) { super(cls, shape); this.name = PythonUtils.toPString(name); @@ -122,8 +93,8 @@ private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString this.qualname = name; } this.enclosingType = enclosingType; - this.executable = executable; - this.signature = executable.signature; + this.functionRootNode = functionRootNode; + this.signature = signature; this.flags = flags; this.defaults = defaults; this.kwDefaults = kwDefaults != null ? kwDefaults : generateKwDefaults(signature); @@ -133,17 +104,17 @@ private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PRootNode rootNode) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode), null, null); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, rootNode, rootNode.getSignature(), null, null); } public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, new Executable(rootNode), slot, slotWrapper); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, rootNode, rootNode.getSignature(), slot, slotWrapper); } public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PBuiltinFunction source, TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, source.executable, slot, slotWrapper); + this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, source.functionRootNode, source.signature, slot, slotWrapper); } public static PKeyword[] generateKwDefaults(Signature signature) { @@ -169,7 +140,7 @@ public static Object[] generateDefaults(int numDefaults) { } public RootNode getFunctionRootNode() { - return executable.getFunctionRootNode(); + return functionRootNode; } /** @@ -189,7 +160,7 @@ public PExternalFunctionWrapper getSlotWrapper() { } public NodeFactory getBuiltinNodeFactory() { - return executable.getBuiltinNodeFactory(); + return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot ? builtinRoot.getFactory() : null; } public int getFlags() { @@ -241,15 +212,15 @@ public Signature getSignature() { } public RootCallTarget getCallTarget() { - return executable.getCallTarget(); + return functionRootNode.getCallTarget(); } public boolean declaresExplicitSelf() { - return executable.declaresExplicitSelf(); + return !(functionRootNode instanceof BuiltinFunctionRootNode builtinRoot) || builtinRoot.declaresExplicitSelf(); } public boolean forceSplitDirectCalls() { - return executable.forceSplitDirectCalls(); + return functionRootNode instanceof BuiltinFunctionRootNode builtinRoot && builtinRoot.getBuiltin().forceSplitDirectCalls(); } public TruffleString getName() { From 72557774d95839bf5da0cc7df642c609dd52bd06 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:21:47 +0200 Subject: [PATCH 19/26] Make cached root node helpers generic --- .../oracle/graal/python/PythonLanguage.java | 33 ++++++++++--------- .../graal/python/builtins/PythonBuiltins.java | 2 +- .../modules/cext/PythonCextTypeBuiltins.java | 9 +++-- .../cext/capi/CApiMemberAccessNodes.java | 8 ++--- .../cext/capi/ExternalFunctionNodes.java | 2 +- .../cext/capi/MethodDescriptorWrapper.java | 5 ++- .../builtins/objects/code/CodeNodes.java | 2 +- .../builtins/objects/mmap/MMapBuiltins.java | 2 +- .../posix/ScandirIteratorBuiltins.java | 2 +- .../objects/tuple/StructSequence.java | 2 +- .../builtins/objects/type/TypeNodes.java | 4 +-- .../builtins/objects/type/slots/TpSlot.java | 4 +-- .../objects/type/slots/TpSlotVarargs.java | 2 +- .../bytecode_dsl/PBytecodeDSLRootNode.java | 2 +- .../graal/python/runtime/AsyncHandler.java | 2 +- .../oracle/graal/python/util/PythonUtils.java | 2 +- 16 files changed, 41 insertions(+), 42 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index b6c55fe2c0..22a4e70942 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -1096,7 +1096,7 @@ public void setCapiCallTarget(int index, RootCallTarget ct) { capiCallTargets[index] = ct; } - public RootNode createCachedRootNode(Function rootNodeFunction, Class key) { + public T createCachedRootNode(Function rootNodeFunction, Class key) { assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length <= 1; assert RootNode.class.isAssignableFrom(key) || key.getConstructors().length == 0 || key.getConstructors()[0].getParameterCount() == 0; return createCachedRootNodeUnsafe(rootNodeFunction, key, true); @@ -1106,13 +1106,13 @@ public RootNode createCachedRootNode(Function rootNode return createCachedRootNodeUnsafe(rootNodeFunction, key, true); } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass, String key) { + public T createCachedRootNode(Function rootNodeFunction, Class nodeClass, String key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } // Variant that should be called at most once per context, because it does not cache the root // node in single context mode - public RootNode initBuiltinRootNode(Function rootNodeFunction, Class nodeClass, String key) { + public T initBuiltinRootNode(Function rootNodeFunction, Class nodeClass, String key) { return createCachedRootNodeUnsafe(rootNodeFunction, false, nodeClass, key); } @@ -1124,33 +1124,33 @@ public RootNode createCachedRootNode(Function rootNode return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, key); } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { + public T createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, String name) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, name); } - public RootNode createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { + public T createCachedRootNode(Function rootNodeFunction, Class nodeClass1, Class nodeClass2, PythonBuiltinClassType type, String name) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name); } - public RootNode createCachedRootNode(Function rootNodeFunction, CodeUnit key) { + public T createCachedRootNode(Function rootNodeFunction, CodeUnit key) { return createCachedRootNodeUnsafe(rootNodeFunction, true, key); } - public RootNode createCachedExternalFunWrapperRootNode(Function rootNodeFunction, + public T createCachedExternalFunWrapperRootNode(Function rootNodeFunction, Class klass, Enum signature, TruffleString name, boolean doArgumentAndResultConversion, boolean isStatic) { return createCachedRootNodeUnsafe(rootNodeFunction, true, klass, signature, name, doArgumentAndResultConversion, isStatic); } - public RootNode createStructSeqIndexedMemberAccessCachedRootNode(Function rootNodeFunction, int memberIndex) { + public T createStructSeqIndexedMemberAccessCachedRootNode(Function rootNodeFunction, int memberIndex) { return createCachedRootNodeUnsafe(rootNodeFunction, true, StructSequence.class, memberIndex); } - public RootNode createCachedPropAccessRootNode(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { + public T createCachedPropAccessRootNode(Function rootNodeFunction, Class nodeClass, String name, int type, int offset) { return createCachedRootNodeUnsafe(rootNodeFunction, true, nodeClass, name, type, offset); } - private RootNode createCachedRootNodeUnsafe(Function rootNodeFunction, Object key, boolean cacheInSingleContext) { + private T createCachedRootNodeUnsafe(Function rootNodeFunction, Object key, boolean cacheInSingleContext) { CompilerAsserts.neverPartOfCompilation(); if (cacheInSingleContext || !singleContext) { return getOrCreateCachedRootNode(rootNodeFunction, key); @@ -1159,18 +1159,19 @@ private RootNode createCachedRootNodeUnsafe(Function r } } - private RootNode createCachedRootNodeUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { + private T createCachedRootNodeUnsafe(Function rootNodeFunction, boolean cacheInSingleContext, Object... cacheKeys) { return createCachedRootNodeUnsafe(rootNodeFunction, Arrays.asList(cacheKeys), cacheInSingleContext); } - private RootNode getOrCreateCachedRootNode(Function rootNodeFunction, Object key) { + @SuppressWarnings("unchecked") + private T getOrCreateCachedRootNode(Function rootNodeFunction, Object key) { CompilerAsserts.neverPartOfCompilation(); if (ImageInfo.inImageRuntimeCode()) { RootNode preinitialized = imageBuildtimeCachedRootNodes.get(key); if (preinitialized != null) { - return preinitialized; + return (T) preinitialized; } - return runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); + return (T) runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); } if (ImageInfo.inImageBuildtimeCode()) { synchronized (imageBuildtimeCachedRootNodes) { @@ -1179,10 +1180,10 @@ private RootNode getOrCreateCachedRootNode(Function ro cached = rootNodeFunction.apply(this); imageBuildtimeCachedRootNodes.put(key, cached); } - return cached; + return (T) cached; } } - return runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); + return (T) runtimeCachedRootNodes.computeIfAbsent(key, k -> rootNodeFunction.apply(this)); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java index cd31e8e4a0..0a5b3c4b47 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java @@ -109,7 +109,7 @@ public void initialize(Python3Core core) { TruffleString tsName = toInternedTruffleStringUncached(builtin.name()); PythonLanguage language = core.getLanguage(); Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : toTruffleStringUncached(builtin.doc()); - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.initBuiltinRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), + BuiltinFunctionRootNode rootNode = language.initBuiltinRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), factory.getNodeClass(), builtin.name()); Signature signature = rootNode.getSignature(); int flags = PBuiltinFunction.getFlags(builtin, signature); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java index 023deb5b55..57ea497e80 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java @@ -132,7 +132,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.EncapsulatingNodeReference; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.strings.TruffleString; @@ -412,14 +411,14 @@ public static GetSetDescriptor createGetSet(TruffleString name, Object cls, long @TruffleBoundary private static PRootNode getterRootNode(TruffleString name, PythonLanguage lang) { - Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.GETTER); - return (PRootNode) lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, GetterRoot.class, PExternalFunctionWrapper.GETTER, name, true, false); + Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.GETTER); + return lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, GetterRoot.class, PExternalFunctionWrapper.GETTER, name, true, false); } @TruffleBoundary private static PRootNode setterRootNode(TruffleString name, PythonLanguage lang) { - Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.SETTER); - return (PRootNode) lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, SetterRoot.class, PExternalFunctionWrapper.SETTER, name, true, false); + Function rootNodeFunction = l -> WrapperDescriptorRootNodesGen.create(l, name, PExternalFunctionWrapper.SETTER); + return lang.createCachedExternalFunWrapperRootNode(rootNodeFunction, SetterRoot.class, PExternalFunctionWrapper.SETTER, name, true, false); } @CApiBuiltin(ret = ArgDescriptor.Void, args = {PyTypeObject, PyBufferProcs}, call = Ignored) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java index 37cc05d45a..350106b656 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiMemberAccessNodes.java @@ -250,7 +250,7 @@ Object doGeneric(@SuppressWarnings("unused") VirtualFrame frame, Object self, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Object owner, TruffleString propertyName, int type, int offset) { CExtToJavaNode asPythonObjectNode = getReadConverterNode(type); - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedPropAccessRootNode( + BuiltinFunctionRootNode rootNode = language.createCachedPropAccessRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadMemberNodeGen.create(type, offset, asPythonObjectNode)), true), ReadMemberNode.class, BUILTIN.name(), type, offset); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); @@ -276,7 +276,7 @@ Object doGeneric(Object self, Object value, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString propertyName) { - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode( + BuiltinFunctionRootNode rootNode = language.createCachedRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(ReadOnlyMemberNodeGen.create(propertyName)), true), ReadOnlyMemberNode.class, BUILTIN.name()); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); @@ -300,7 +300,7 @@ static Object doGeneric(Object self, @SuppressWarnings("unused") Object value, @TruffleBoundary public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString propertyName) { - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode( + BuiltinFunctionRootNode rootNode = language.createCachedRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(BadMemberDescrNodeGen.create()), true), BadMemberDescrNode.class, BUILTIN.name()); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); @@ -599,7 +599,7 @@ public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Ob return BadMemberDescrNode.createBuiltinFunction(language, propertyName); } // - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedPropAccessRootNode( + BuiltinFunctionRootNode rootNode = language.createCachedPropAccessRootNode( l -> new BuiltinFunctionRootNode(l, BUILTIN, new PrototypeNodeFactory<>(WriteMemberNodeGen.create(type, offset)), true), WriteMemberNode.class, BUILTIN.name(), type, offset); int flags = PBuiltinFunction.getFlags(BUILTIN, rootNode.getSignature()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java index 10e0584da5..124d0894c5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java @@ -482,7 +482,7 @@ public enum PExternalFunctionWrapper implements NativeCExtSymbol { @TruffleBoundary static PRootNode getOrCreateRootNode(PExternalFunctionWrapper sig, PythonLanguage language, TruffleString name) { - return (PRootNode) language.createCachedExternalFunWrapperRootNode(l -> WrapperDescriptorRootNodesGen.create(l, name, sig), sig.rootNodeClass, sig, name, true, false); + return language.createCachedExternalFunWrapperRootNode(l -> WrapperDescriptorRootNodesGen.create(l, name, sig), sig.rootNodeClass, sig, name, true, false); } /** diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java index c82fe409ab..284bebc43b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/MethodDescriptorWrapper.java @@ -68,7 +68,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleLogger; -import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.strings.TruffleString; public enum MethodDescriptorWrapper implements NativeCExtSymbol { @@ -126,7 +125,7 @@ public ArgDescriptor[] getArguments() { @TruffleBoundary static PRootNode getOrCreateRootNode(PythonLanguage language, MethodDescriptorWrapper sig, TruffleString name, boolean isStatic) { Class nodeKlass; - Function rootNodeFunction = switch (sig) { + Function rootNodeFunction = switch (sig) { case KEYWORDS -> { nodeKlass = MethKeywordsRoot.class; yield l -> new MethKeywordsRoot(l, name, isStatic, sig); @@ -156,7 +155,7 @@ static PRootNode getOrCreateRootNode(PythonLanguage language, MethodDescriptorWr yield (l -> new MethMethodRoot(l, name, isStatic, sig)); } }; - return (PRootNode) language.createCachedExternalFunWrapperRootNode(rootNodeFunction, nodeKlass, sig, name, true, isStatic); + return language.createCachedExternalFunWrapperRootNode(rootNodeFunction, nodeKlass, sig, name, true, isStatic); } /** diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java index 7ee22b3c4f..c59265e94a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java @@ -144,7 +144,7 @@ private static PCode createCode(PythonLanguage language, int argCount, RootCallTarget ct; Signature signature; if (codedata.length == 0) { - PRootNode rootNode = (PRootNode) language.createCachedRootNode(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); + PRootNode rootNode = language.createCachedRootNode(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); /* * We need to create a proper signature because this code path is used to create * fake code objects for duck-typed function-like objects, such as Cython functions. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 90ce7a6f89..5e12562602 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -960,7 +960,7 @@ public void execute(PythonContext context, Access access) { return; } PythonLanguage language = context.getLanguage(); - ReleaserRootNode rootNode = (ReleaserRootNode) language.createCachedRootNode(MMapBuiltins.ReleaseCallback.ReleaserRootNode::new, + ReleaserRootNode rootNode = language.createCachedRootNode(MMapBuiltins.ReleaseCallback.ReleaserRootNode::new, MMapBuiltins.ReleaseCallback.ReleaserRootNode.class); rootNode.getCallTarget().call(ref); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java index 532e7db8c5..6e5b03fee1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/posix/ScandirIteratorBuiltins.java @@ -169,7 +169,7 @@ public void execute(PythonContext context, Access access) { return; } PythonLanguage language = context.getLanguage(); - ReleaserRootNode rootNode = (ReleaserRootNode) language.createCachedRootNode(ReleaserRootNode::new, ReleaserRootNode.class); + ReleaserRootNode rootNode = language.createCachedRootNode(ReleaserRootNode::new, ReleaserRootNode.class); rootNode.getCallTarget().call(ref); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java index f242808d09..968507476a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/StructSequence.java @@ -223,7 +223,7 @@ private static void copyMethod(PythonLanguage language, PythonAbstractClass klas } private static void createMember(PythonLanguage language, Object klass, TruffleString name, TruffleString doc, int idx) { - GetStructMemberNode rootNode = (GetStructMemberNode) language.createStructSeqIndexedMemberAccessCachedRootNode((l) -> new GetStructMemberNode(l, idx), idx); + GetStructMemberNode rootNode = language.createStructSeqIndexedMemberAccessCachedRootNode((l) -> new GetStructMemberNode(l, idx), idx); PBuiltinFunction getter = PFactory.createBuiltinFunction(language, name, klass, 0, 0, rootNode); GetSetDescriptor callable = PFactory.createGetSetDescriptor(language, getter, null, name, klass, false); if (doc != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 944d872fc2..5ad7999c80 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -2327,7 +2327,7 @@ private static void addDictDescrAttribute(PythonAbstractClass[] basesArray, Pyth // initialized yet if ((!hasPythonClassBases(basesArray) && LookupAttributeInMRONode.lookupSlowPath(pythonClass, T___DICT__) == PNone.NO_VALUE) || basesHaveSlots(basesArray)) { Builtin dictBuiltin = ObjectBuiltins.DictNode.class.getAnnotation(Builtin.class); - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) PythonLanguage.get(null).createCachedRootNode( + BuiltinFunctionRootNode rootNode = PythonLanguage.get(null).createCachedRootNode( l -> new BuiltinFunctionRootNode(l, dictBuiltin, ObjectBuiltinsFactory.DictNodeFactory.getInstance(), true), ObjectBuiltins.DictNode.class); setAttribute(T___DICT__, dictBuiltin, rootNode, pythonClass, language); } @@ -2337,7 +2337,7 @@ private static void addDictDescrAttribute(PythonAbstractClass[] basesArray, Pyth private static void addWeakrefDescrAttribute(PythonClass pythonClass, PythonLanguage language) { if (LookupAttributeInMRONode.lookupSlowPath(pythonClass, T___WEAKREF__) == PNone.NO_VALUE) { Builtin builtin = GetWeakRefsNode.class.getAnnotation(Builtin.class); - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) PythonLanguage.get(null).createCachedRootNode( + BuiltinFunctionRootNode rootNode = PythonLanguage.get(null).createCachedRootNode( l -> new BuiltinFunctionRootNode(l, builtin, WeakRefModuleBuiltinsFactory.GetWeakRefsNodeFactory.getInstance(), true), GetWeakRefsNode.class); setAttribute(T___WEAKREF__, builtin, rootNode, pythonClass, language); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java index 99a1113df1..ce71b0569c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlot.java @@ -309,7 +309,7 @@ final PBuiltinFunction createBuiltin(Python3Core core, Object type, TruffleStrin Class nodeClass = NodeFactoryBase.getWrappedNodeClass(factory); validateSlotNode(factory, nodeClass, slotSignature); PythonBuiltinClassType builtinType = type instanceof PythonBuiltinClassType bt ? bt : null; - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) core.getLanguage().createCachedRootNode( + BuiltinFunctionRootNode rootNode = core.getLanguage().createCachedRootNode( l -> new BuiltinFunctionRootNode(l, builtin, factory, true, builtinType), factory.getNodeClass(), nodeClass, builtinType, name); PBuiltinFunction function = PFactory.createWrapperDescriptor(core.getLanguage(), tsName, type, numDefaults(builtin), 0, rootNode, this, wrapper); @@ -327,7 +327,7 @@ static BuiltinFunctionRootNode createSlotRootNode(PythonLanguage language, Built Builtin builtin = new Slot2Builtin(slotSignature, name, signature); Class nodeClass = NodeFactoryBase.getWrappedNodeClass(factory); validateSlotNode(factory, nodeClass, slotSignature); - return (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, true), factory.getNodeClass(), nodeClass, name); + return language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, true), factory.getNodeClass(), nodeClass, name); } private static void validateSlotNode(NodeFactory factory, Class nodeClass, SlotSignature slotSignature) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java index dc440388fb..bf8813f3f0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotVarargs.java @@ -212,7 +212,7 @@ public PBuiltinMethod createBuiltin(Python3Core core, Object type, TruffleString * 'WrapTpNew' holds the type in a field and uses that to do the check. The dropping is * achieved by using `declaresExplicitSelf = false`. */ - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, false, builtinType), + BuiltinFunctionRootNode rootNode = language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, factory, false, builtinType), nodeClass, nodeClass, builtinType, J___NEW__); return PFactory.createNewWrapper(language, type, defaults, kwDefaults, rootNode, this); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java index 214874f60e..745a33e299 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java @@ -452,7 +452,7 @@ protected void prepareForInstrumentation(Set> materializedTags) { PythonLanguage language = getLanguage(); for (Object constant : co.constants) { if (constant instanceof BytecodeDSLCodeUnit codeUnit) { - PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, getSource()), codeUnit); + PBytecodeDSLRootNode rootNode = language.createCachedRootNode(l -> codeUnit.createRootNode(l, getSource()), codeUnit); rootNode.getCallTarget(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 103f383a8e..82f84611ea 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -344,7 +344,7 @@ public boolean setsUpCalleeContext() { AsyncHandler(PythonContext context) { this.context = new WeakReference<>(context); - this.rootNode = (CallRootNode) context.getLanguage().createCachedRootNode(CallRootNode::new, CallRootNode.class); + this.rootNode = context.getLanguage().createCachedRootNode(CallRootNode::new, CallRootNode.class); if (PythonOptions.AUTOMATIC_ASYNC_ACTIONS) { this.executorService = Executors.newScheduledThreadPool(6, runnable -> { Thread t = Executors.defaultThreadFactory().newThread(runnable); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java index 981c7240b8..da3fae1f89 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java @@ -758,7 +758,7 @@ public static Object[] toArray(List list) { public static PBuiltinFunction createMethod(PythonLanguage language, Object klass, NodeFactory nodeFactory, Object type, int numDefaults) { Class nodeClass = nodeFactory.getNodeClass(); Builtin builtin = nodeClass.getAnnotation(Builtin.class); - BuiltinFunctionRootNode rootNode = (BuiltinFunctionRootNode) language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, nodeFactory, true), nodeClass); + BuiltinFunctionRootNode rootNode = language.createCachedRootNode(l -> new BuiltinFunctionRootNode(l, builtin, nodeFactory, true), nodeClass); return createMethod(klass, builtin, rootNode, type, numDefaults); } From ddea0fd6869520e4b947239fd1ed11bfc3455a73 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:22:09 +0200 Subject: [PATCH 20/26] Mark lazy function call target path slow --- .../graal/python/builtins/objects/function/PFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java index c47348da59..a23486255d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java @@ -171,7 +171,7 @@ public PCode getCode() { public RootCallTarget getCallTarget() { RootCallTarget ct = callTarget; - if (ct == null) { + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, ct == null)) { ct = getCode().getRootCallTarget(); callTarget = ct; } From f2382ec3594fe34a08cb36261f00f32a46522e4c Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:23:09 +0200 Subject: [PATCH 21/26] Collapse builtin function constructors --- .../objects/function/PBuiltinFunction.java | 18 +----------------- .../graal/python/runtime/object/PFactory.java | 11 ++++++----- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index 488474270c..392fd0ee4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -43,7 +43,6 @@ import com.oracle.graal.python.builtins.objects.str.StringUtils; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.builtins.objects.type.slots.TpSlot; -import com.oracle.graal.python.nodes.PRootNode; import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.runtime.object.PFactory; @@ -82,7 +81,7 @@ public final class PBuiltinFunction extends PythonBuiltinObject implements Bound @CompilationFinal(dimensions = 1) private final Object[] defaults; @CompilationFinal(dimensions = 1) private final PKeyword[] kwDefaults; - private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootNode functionRootNode, + public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootNode functionRootNode, Signature signature, TpSlot slot, PExternalFunctionWrapper slotWrapper) { super(cls, shape); @@ -102,21 +101,6 @@ private PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString this.slotWrapper = slotWrapper; } - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, - PRootNode rootNode) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, rootNode, rootNode.getSignature(), null, null); - } - - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, - PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, rootNode, rootNode.getSignature(), slot, slotWrapper); - } - - public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, PBuiltinFunction source, - TpSlot slot, PExternalFunctionWrapper slotWrapper) { - this(cls, shape, name, enclosingType, defaults, kwDefaults, flags, source.functionRootNode, source.signature, slot, slotWrapper); - } - public static PKeyword[] generateKwDefaults(Signature signature) { TruffleString[] keywordNames = signature.getKeywordNames(); PKeyword[] kwDefaults = PKeyword.create(keywordNames.length); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 66ac86497e..11ff2bf414 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -517,23 +517,24 @@ public static PFunction createFunction(PythonLanguage language, TruffleString na public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode) { return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode); + PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, rootNode.getSignature(), null, null); } public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, PRootNode rootNode) { - return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, rootNode); + return new PBuiltinFunction(PythonBuiltinClassType.PBuiltinFunction, PythonBuiltinClassType.PBuiltinFunction.getInstanceShape(language), name, type, defaults, kw, flags, rootNode, + rootNode.getSignature(), null, null); } public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, int numDefaults, int flags, PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, - PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, slot, slotWrapper); + PBuiltinFunction.generateDefaults(numDefaults), null, flags, rootNode, rootNode.getSignature(), slot, slotWrapper); } public static PBuiltinFunction createWrapperDescriptor(PythonLanguage language, TruffleString name, Object type, Object[] defaults, PKeyword[] kw, int flags, PRootNode rootNode, TpSlot slot, PExternalFunctionWrapper slotWrapper) { return new PBuiltinFunction(PythonBuiltinClassType.WrapperDescriptor, PythonBuiltinClassType.WrapperDescriptor.getInstanceShape(language), name, type, defaults, kw, flags, - rootNode, slot, slotWrapper); + rootNode, rootNode.getSignature(), slot, slotWrapper); } public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object type, Object[] defaults, PKeyword[] kwdefaults, PRootNode rootNode, TpSlot slot) { @@ -545,7 +546,7 @@ public static PBuiltinMethod createNewWrapper(PythonLanguage language, Object ty public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, PBuiltinFunction function, Object klass) { PythonBuiltinClassType type = (PythonBuiltinClassType) function.getPythonClass(); return new PBuiltinFunction(type, type.getInstanceShape(language), function.getName(), klass, - function.getDefaults(), function.getKwDefaults(), function.getFlags(), function, + function.getDefaults(), function.getKwDefaults(), function.getFlags(), function.getFunctionRootNode(), function.getSignature(), function.getSlot(), function.getSlotWrapper()); } From 707df4767035130aec41b40d066b0fe6eef161f5 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:23:48 +0200 Subject: [PATCH 22/26] Collapse code object constructors --- .../python/builtins/objects/code/PCode.java | 53 ++----------------- .../graal/python/runtime/object/PFactory.java | 27 +++++----- 2 files changed, 19 insertions(+), 61 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 21e2472985..bf1e037f2e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -135,52 +135,7 @@ public final class PCode extends PythonBuiltinObject { // tuple of names of cell variables (referenced by containing scopes) private TruffleString[] cellvars; - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget) { - this(cls, instanceShape, callTarget, null); - } - - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, TruffleString filename) { - super(cls, instanceShape); - this.rootNode = callTarget.getRootNode(); - this.signature = Signature.fromCallTarget(callTarget); - this.filename = filename; - } - - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, int flags, int firstlineno, byte[] linetable, TruffleString filename) { - this(cls, instanceShape, callTarget); - this.flags = flags; - this.firstlineno = firstlineno; - this.linetable = linetable; - this.filename = filename; - } - - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { - this(cls, instanceShape, callTarget, signature, codeUnit.varnames.length, -1, -1, null, null, - null, null, null, filename, - codeUnit.name, codeUnit.qualname, -1, codeUnit.srcOffsetTable); - } - - public PCode(Object cls, Shape instanceShape, RootCallTarget callTarget, Signature signature, int nlocals, - int stacksize, int flags, Object[] constants, TruffleString[] names, - TruffleString[] varnames, TruffleString[] freevars, TruffleString[] cellvars, - TruffleString filename, TruffleString name, TruffleString qualname, - int firstlineno, byte[] linetable) { - this(cls, instanceShape, (PRootNode) callTarget.getRootNode(), signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); - } - - public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { - this(cls, instanceShape, rootNode, signature, codeUnit.varnames.length, -1, -1, null, null, - null, null, null, filename, - codeUnit.name, codeUnit.qualname, -1, codeUnit.srcOffsetTable); - } - - public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { - this(cls, instanceShape, rootNode, signature, codeUnit.varnames.length, -1, -1, null, null, - null, null, null, filename, - codeUnit.name, codeUnit.qualname, -1, null); - } - - public PCode(Object cls, Shape instanceShape, PRootNode rootNode, Signature signature, int nlocals, + public PCode(Object cls, Shape instanceShape, RootNode rootNode, Signature signature, int nlocals, int stacksize, int flags, Object[] constants, TruffleString[] names, TruffleString[] varnames, TruffleString[] freevars, TruffleString[] cellvars, TruffleString filename, TruffleString name, TruffleString qualname, @@ -518,7 +473,7 @@ public PCode getOrCreateChildCode(int index, BytecodeDSLCodeUnit codeUnit) { private PCode createCode(BytecodeDSLCodeUnit codeUnit) { PBytecodeDSLRootNode outerRootNode = (PBytecodeDSLRootNode) getRootNodeForExtraction(); PythonLanguage language = outerRootNode.getLanguage(); - PBytecodeDSLRootNode rN = (PBytecodeDSLRootNode) language.createCachedRootNode(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); + PBytecodeDSLRootNode rN = language.createCachedRootNode(l -> codeUnit.createRootNode(l, outerRootNode.getSource()), codeUnit); return PFactory.createCode(language, rN, rN.getSignature(), codeUnit, getFilename()); } @@ -536,8 +491,8 @@ public PCode getOrCreateChildCode(int index, BytecodeCodeUnit codeUnit) { private PCode createCode(BytecodeCodeUnit codeUnit) { PBytecodeRootNode outerRootNode = (PBytecodeRootNode) getRootNodeForExtraction(); PythonLanguage language = outerRootNode.getLanguage(); - PRootNode executableRootNode = (PRootNode) language.createCachedRootNode( - l -> PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getSource(), outerRootNode.isInternal()), codeUnit); + PRootNode executableRootNode = language.createCachedRootNode( + l -> (PRootNode) PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getSource(), outerRootNode.isInternal()), codeUnit); RootNode rN = executableRootNode; if (executableRootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { rN = generatorRoot.getBytecodeRootNode(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 11ff2bf414..4ab2d7931a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -258,6 +258,7 @@ import com.oracle.truffle.api.bytecode.ContinuationRootNode; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.tools.profiler.CPUSampler; @@ -1075,27 +1076,31 @@ public static PZip createZip(Object cls, Shape shape, Object[] iterables, boolea } public static PCode createCode(PythonLanguage language, RootCallTarget ct) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct); + return createCode(language, ct, null); } public static PCode createCode(PythonLanguage language, RootCallTarget ct, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, filename); + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct.getRootNode(), Signature.fromCallTarget(ct), + -1, -1, -1, null, null, null, null, null, filename, null, null, -1, null); } public static PCode createCode(PythonLanguage language, RootCallTarget ct, int flags, int firstlineno, byte[] linetable, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct, flags, firstlineno, linetable, filename); + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), ct.getRootNode(), Signature.fromCallTarget(ct), + -1, -1, flags, null, null, null, null, null, filename, null, null, firstlineno, linetable); } public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, codeUnit, filename); + return createCode(language, callTarget.getRootNode(), signature, codeUnit, filename); } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); + public static PCode createCode(PythonLanguage language, RootNode rootNode, Signature signature, BytecodeCodeUnit codeUnit, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, + codeUnit.varnames.length, -1, -1, null, null, null, null, null, filename, codeUnit.name, codeUnit.qualname, -1, codeUnit.srcOffsetTable); } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, codeUnit, filename); + public static PCode createCode(PythonLanguage language, RootNode rootNode, Signature signature, BytecodeDSLCodeUnit codeUnit, TruffleString filename) { + return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), rootNode, signature, + codeUnit.varnames.length, -1, -1, null, null, null, null, null, filename, codeUnit.name, codeUnit.qualname, -1, null); } public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, int nlocals, @@ -1104,12 +1109,10 @@ public static PCode createCode(PythonLanguage language, RootCallTarget callTarge TruffleString[] freevars, TruffleString[] cellvars, TruffleString filename, TruffleString name, TruffleString qualname, int firstlineno, byte[] linetable) { - return new PCode(PythonBuiltinClassType.PCode, PythonBuiltinClassType.PCode.getInstanceShape(language), callTarget, signature, - nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, - filename, name, qualname, firstlineno, linetable); + return createCode(language, callTarget.getRootNode(), signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); } - public static PCode createCode(PythonLanguage language, PRootNode rootNode, Signature signature, int nlocals, + public static PCode createCode(PythonLanguage language, RootNode rootNode, Signature signature, int nlocals, int stacksize, int flags, Object[] constants, TruffleString[] names, TruffleString[] varnames, TruffleString[] freevars, TruffleString[] cellvars, From c9cb30fab180fb3e2052c1ceb8db190069a4a70e Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:24:01 +0200 Subject: [PATCH 23/26] Use code root node for disassembly --- .../com/oracle/graal/python/builtins/objects/code/PCode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index bf1e037f2e..7370241817 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -629,7 +629,7 @@ public String toString() { @TruffleBoundary public String toDisassembledString(boolean quickened) { - RootNode rN = getRootCallTarget().getRootNode(); + RootNode rN = getRootNode(); if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER && rN instanceof PBytecodeDSLRootNode dslRoot) { return dslRoot.getCodeUnit().toString(quickened, dslRoot); } else if (rN instanceof PBytecodeGeneratorRootNode r) { From 6daaac91ba95c9ed71b51659ada454876eaa5504 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 12 May 2026 14:24:23 +0200 Subject: [PATCH 24/26] Avoid eager call target for code creation --- .../python/builtins/objects/code/CodeNodes.java | 14 +++++++------- .../graal/python/runtime/object/PFactory.java | 9 --------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java index c59265e94a..d26d848a8e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java @@ -141,10 +141,10 @@ private static PCode createCode(PythonLanguage language, int argCount, TruffleString name = PythonUtils.internString(uninternedName); qualname = PythonUtils.internString(qualname); - RootCallTarget ct; + PRootNode rootNode; Signature signature; if (codedata.length == 0) { - PRootNode rootNode = language.createCachedRootNode(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); + rootNode = language.createCachedRootNode(l -> new BadOPCodeNode(l, name), BadOPCodeNode.class, name.toJavaStringUncached()); /* * We need to create a proper signature because this code path is used to create * fake code objects for duck-typed function-like objects, such as Cython functions. @@ -167,13 +167,13 @@ private static PCode createCode(PythonLanguage language, int argCount, kwOnlyNames); return PFactory.createCode(language, rootNode, signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); } else { - ct = deserializeForBytecodeInterpreter(language, codedata, cellvars, freevars, flags); - signature = ((PRootNode) ct.getRootNode()).getSignature(); + rootNode = deserializeForBytecodeInterpreter(language, codedata, cellvars, freevars, flags); + signature = rootNode.getSignature(); } - return PFactory.createCode(language, ct, signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); + return PFactory.createCode(language, rootNode, signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); } - private static RootCallTarget deserializeForBytecodeInterpreter(PythonLanguage language, byte[] data, TruffleString[] cellvars, TruffleString[] freevars, int flags) { + private static PRootNode deserializeForBytecodeInterpreter(PythonLanguage language, byte[] data, TruffleString[] cellvars, TruffleString[] freevars, int flags) { CodeUnit codeUnit = MarshalModuleBuiltins.deserializeCodeUnit(null, language, data); RootNode rootNode; @@ -199,7 +199,7 @@ private static RootCallTarget deserializeForBytecodeInterpreter(PythonLanguage l rootNode = new PBytecodeGeneratorFunctionRootNode(language, rootNode.getFrameDescriptor(), (PBytecodeRootNode) rootNode, code.name); } } - return PythonUtils.getOrCreateCallTarget(rootNode); + return (PRootNode) rootNode; } @NeverDefault diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 4ab2d7931a..e1eb2448de 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -1103,15 +1103,6 @@ public static PCode createCode(PythonLanguage language, RootNode rootNode, Signa codeUnit.varnames.length, -1, -1, null, null, null, null, null, filename, codeUnit.name, codeUnit.qualname, -1, null); } - public static PCode createCode(PythonLanguage language, RootCallTarget callTarget, Signature signature, int nlocals, - int stacksize, int flags, Object[] constants, - TruffleString[] names, TruffleString[] varnames, - TruffleString[] freevars, TruffleString[] cellvars, - TruffleString filename, TruffleString name, TruffleString qualname, - int firstlineno, byte[] linetable) { - return createCode(language, callTarget.getRootNode(), signature, nlocals, stacksize, flags, constants, names, varnames, freevars, cellvars, filename, name, qualname, firstlineno, linetable); - } - public static PCode createCode(PythonLanguage language, RootNode rootNode, Signature signature, int nlocals, int stacksize, int flags, Object[] constants, TruffleString[] names, TruffleString[] varnames, From 0d9d7eca0f52af8cb924be9d52aaddfda429fe77 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 13 May 2026 13:40:10 +0200 Subject: [PATCH 25/26] Store the compilation final calltarget in PCode again --- .../graal/python/builtins/objects/code/PCode.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 7370241817..027bbdeef3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -70,6 +70,7 @@ import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage; import com.oracle.graal.python.util.PythonUtils; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.bytecode.BytecodeNode; @@ -101,6 +102,7 @@ public final class PCode extends PythonBuiltinObject { public static final int CO_GRAALPYHON_MODULE = 0x1000; private final RootNode rootNode; + @CompilationFinal private RootCallTarget callTarget; private final Signature signature; // number of local variables @@ -578,7 +580,13 @@ public Signature getSignature() { } public RootCallTarget getRootCallTarget() { - return rootNode.getCallTarget(); + RootCallTarget ct = callTarget; + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, ct == null)) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + ct = rootNode.getCallTarget(); + callTarget = ct; + } + return ct; } @ExportMessage From 02fba27a19d96cf7ce6eb7aa04eded524e5133a4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 19 May 2026 11:58:32 +0200 Subject: [PATCH 26/26] It's ok in megamorphic and generic cases that we lazily initialize PCode calltargets --- .../graal/python/builtins/objects/code/PCode.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 027bbdeef3..55acb7cb66 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -582,7 +582,18 @@ public Signature getSignature() { public RootCallTarget getRootCallTarget() { RootCallTarget ct = callTarget; if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, ct == null)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); + if (CompilerDirectives.inCompiledCode() && CompilerDirectives.isPartialEvaluationConstant(this)) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + ct = initializeCallTarget(); + } + return ct; + } + + @TruffleBoundary + private RootCallTarget initializeCallTarget() { + RootCallTarget ct = callTarget; + if (ct == null) { ct = rootNode.getCallTarget(); callTarget = ct; }