Skip to content

[GR-67626] Optimize host inlining of attribute lookup in GraalPy #524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
444f693
Replace GetAttributeNode by GetFixedAttributeNode
eregon Jul 7, 2025
6a81c77
Add env files to conveniently dump host inlining decisions
eregon Jul 8, 2025
e7e153e
Remove duplicate specializations in GetClassNode
eregon Jul 8, 2025
c4fe230
Use an explicit guard for GetClassNode#getForeign to save code size
eregon Jul 8, 2025
7148716
Use CompilerAsserts.neverPartOfCompilation() instead of comment
eregon Jul 9, 2025
e571daa
Remove extra specialization for ObjectBuiltins.GetAttributeNode
eregon Jul 7, 2025
b9354ba
Refactor ObjectBuiltins.GetAttributeNode to be as similar as possible…
eregon Jul 10, 2025
8a11c5a
Replace CastToTruffleStringCheckedNode by arity-specific variants to …
eregon Jul 10, 2025
b1bf8b3
Fix docs
eregon Jul 10, 2025
b748204
Remove duplicate specialization in ModuleBuiltins.ModuleGetattributeNode
eregon Jul 10, 2025
120a176
Use CastToTruffleStringChecked*Node instead of CastToTruffleStringNode
eregon Jul 10, 2025
592c519
Remove redundant GetFixedAttributeNode#executeObject() method
eregon Jul 10, 2025
9567c2b
Add StringUtils.EqualNode to wrap TruffleString.EqualNode with @Inlin…
eregon Jul 10, 2025
7ed17a7
Align ThreadLocalBuiltins.GetAttributeNode with ObjectBuiltins.GetAtt…
eregon Jul 10, 2025
d76ad7b
Add MergedObjectTypeModuleGetAttributeNode
eregon Jul 10, 2025
d7d2f61
Rename GetPythonObjectClassNode for clarity in host inlining decisions
eregon Jul 18, 2025
f0b1a1c
[GR-66471] DSL-inline GetPythonObjectClassNode in GetClassNode to hos…
eregon Jul 18, 2025
cca7cd9
Add @InliningCutoff to ModuleBuiltins.HandleGetattrExceptionNode
eregon Jul 18, 2025
587b618
Add @InliningCutoff in PRaiseNode
eregon Jul 18, 2025
8c5ae76
GetPythonObjectClassNode#doInitialClass should replace doConstantClass
eregon Jul 18, 2025
44d74a1
Do not use DynamicObjectLibrary for just getting the Shape flags
eregon Jul 18, 2025
5ad4d16
Update imports
eregon Jul 29, 2025
76afa98
Make PythonObject#initialPythonClass non-final and rename to PythonOb…
eregon Jul 18, 2025
d06b0f0
Use PNone.NO_VALUE instead of null for DynamicObjectLibrary#setDynami…
eregon Jul 25, 2025
6ba79c1
Merged generic cases in LookupAttributeInMRONode.Dynamic to have a si…
eregon Jul 21, 2025
37de3e6
Merge the first two specializations of LookupAttributeInMRONode
eregon Jul 21, 2025
29e374f
Extract slow-path/@InliningCutoff specializations of LookupAttributeI…
eregon Jul 21, 2025
dc9fc06
Remove duplicated specialization in PyObjectGetMethod
eregon Jul 21, 2025
4160318
Use @NonIdempotent instead of passing an extra dynamic argument
eregon Jul 22, 2025
110a75c
Remove duplicate specializations in GenericSetAttrNode and callers
eregon Jul 22, 2025
c154af0
Optimize IsTypeNode by avoiding native call for native objects
eregon Jul 25, 2025
8bb10ea
Optimize GetDictIfExistsNode for native types
eregon Jul 25, 2025
3c16c81
Unify ReadAttributeFromObjectNode 2 subclasses into ReadAttributeFrom…
eregon Jul 22, 2025
dc57688
Create the dict eagerly for modules so it's always there
eregon Jul 30, 2025
dc3b6c6
Avoid subclasses in WriteAttributeToObjectNode
eregon Jul 22, 2025
67b6b2f
Document StgDictObject
eregon Jul 25, 2025
256fb7b
Document ReadAttributeFromPythonObjectNode
eregon Jul 28, 2025
cfd056f
Document how to print a Python traceback in the Java debugger
eregon Jul 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions ci/graal/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@
"labsjdk-ee-25Debug": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-debug", "platformspecific": true },
"labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true },

"oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+7", "platformspecific": true, "extrabundles": ["static-libs"]},
"labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01", "platformspecific": true },
"labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-debug", "platformspecific": true },
"labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-sulong", "platformspecific": true },
"labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01", "platformspecific": true },
"labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-debug", "platformspecific": true },
"labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-sulong", "platformspecific": true }
"oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+8", "platformspecific": true, "extrabundles": ["static-libs"]},
"labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01", "platformspecific": true },
"labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-debug", "platformspecific": true },
"labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-sulong", "platformspecific": true },
"labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01", "platformspecific": true },
"labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-debug", "platformspecific": true },
"labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-sulong", "platformspecific": true }
},

"eclipse": {
Expand Down
5 changes: 3 additions & 2 deletions docs/contributor/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ If the IDE was initialized properly by using the command mentioned above, the ex

Both of these commands also work when you have a `graalpy` executable, e.g. inside a `venv`.

For debugging the C API and native extensions, first make sure you rebuild (`mx clean` first!) graalpything with the environment variable `CFLAGS=-g` set.
For debugging the C API and native extensions, first make sure you rebuild (`mx clean` first!) graalpython with the environment variable `CFLAGS=-g` set.
This will keep debug symbols in our C API implementation which should allow you to use `gdb` or [`rr`](https://rr-project.org/) to debug.
When you build an SVM image, debugging the entire application is possible, and there are [docs](https://www.graalvm.org/reference-manual/native-image/guides/debug-native-image-process/) to see Java code when inside the native debugger.
Make sure you find and keep the `libpythonvm.so.debug` file around next to your GraalPy build, you can find it somewhere under `graal/sdk/mxbuild`.
Make sure you find and keep the `libpythonvm.so.debug` file around next to your GraalPy build, you can find it under `mxbuild/*/libpythonvm`.

## Advanced Commands to Develop and Debug

Expand All @@ -149,6 +149,7 @@ mx python-gate --tags python-unittest

If some of the tests fail, you can re-run just a single test like this, substituting TEST-SELECTOR with the test you want to run. You can use the whole failed test name including the path as the selector.
Note that you can insert `-d` to debug on the Java level or use `--inspect` to debug in the Chrome debugger.
Use `com.oracle.graal.python.runtime.exception.ExceptionUtils.printPythonLikeStackTrace()` in the Java debugger to print the current Python traceback on `stderr`.

```bash
mx [-d] graalpytest [--inspect] TEST-SELECTOR
Expand Down
4 changes: 0 additions & 4 deletions graalpython/com.oracle.graal.python.cext/src/capi.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,6 @@ PyAPI_FUNC(void*) GraalPyPrivate_PointerAddOffset(void* x, Py_ssize_t y) {
return (char *)x + y;
}

PyAPI_FUNC(int) GraalPyPrivate_SubclassCheck(PyObject* type) {
return PyType_FastSubclass(Py_TYPE(type), Py_TPFLAGS_TYPE_SUBCLASS);
}

// Implements the basesisze check in typeobject.c:_PyObject_GetState
PyAPI_FUNC(int) GraalPyPrivate_CheckBasicsizeForGetstate(PyTypeObject* type, int slot_num) {
Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
import com.oracle.graal.python.compiler.ParserCallbacksImpl;
import com.oracle.graal.python.compiler.bytecode_dsl.BytecodeDSLCompiler;
import com.oracle.graal.python.compiler.bytecode_dsl.BytecodeDSLCompiler.BytecodeDSLCompilerResult;
import com.oracle.graal.python.nodes.HiddenAttr;
import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode;
import com.oracle.graal.python.nodes.bytecode_dsl.BytecodeDSLCodeUnit;
import com.oracle.graal.python.nodes.call.CallDispatchers;
Expand Down Expand Up @@ -1043,7 +1042,7 @@ public Shape getEmptyShape() {

public Shape getShapeForClass(PythonAbstractClass klass) {
if (isSingleContext()) {
return Shape.newBuilder(getEmptyShape()).addConstantProperty(HiddenAttr.getClassHiddenKey(), klass, 0).build();
return Shape.newBuilder(getEmptyShape()).dynamicType(klass).build();
} else {
return getEmptyShape();
}
Expand All @@ -1065,7 +1064,7 @@ public Shape getBuiltinTypeInstanceShape(PythonBuiltinClassType type) {

private Shape createBuiltinShape(PythonBuiltinClassType type, int ordinal) {
Shape shape;
Shape.DerivedBuilder shapeBuilder = Shape.newBuilder(getEmptyShape()).addConstantProperty(HiddenAttr.getClassHiddenKey(), type, 0);
Shape.DerivedBuilder shapeBuilder = Shape.newBuilder(getEmptyShape()).dynamicType(type);
if (!type.isBuiltinWithDict()) {
shapeBuilder.shapeFlags(PythonObject.HAS_SLOTS_BUT_NO_DICT_FLAG);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
import com.oracle.graal.python.nodes.attributes.GetFixedAttributeNode;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
Expand Down Expand Up @@ -178,8 +178,8 @@ static Object getCurrentLoop(VirtualFrame frame, Object ignored,
@Cached CallNode callGetPolicy,
@Cached CallNode callGetLoop,
@Cached AbstractImportNode.ImportName importName,
@Cached(parameters = "T_GET_EVENT_LOOP") GetAttributeNode.GetFixedAttributeNode getGetLoop,
@Cached(parameters = "T_GET_EVENT_LOOP_POLICY") GetAttributeNode.GetFixedAttributeNode getGetLoopPolicy) {
@Cached(parameters = "T_GET_EVENT_LOOP") GetFixedAttributeNode getGetLoop,
@Cached(parameters = "T_GET_EVENT_LOOP_POLICY") GetFixedAttributeNode getGetLoopPolicy) {
Object eventLoop = context.getThreadState(context.getLanguage(inliningTarget)).getRunningEventLoop();
if (eventLoop == null) {
Object asyncio = importName.execute(frame, context, context.getBuiltins(), T_ASYNCIO_EVENTS, PNone.NONE, PythonUtils.EMPTY_TRUFFLESTRING_ARRAY, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@
import com.oracle.graal.python.nodes.SpecialMethodNames;
import com.oracle.graal.python.nodes.StringLiterals;
import com.oracle.graal.python.nodes.argument.ReadArgumentNode;
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
import com.oracle.graal.python.nodes.attributes.GetFixedAttributeNode;
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromModuleNode;
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
import com.oracle.graal.python.nodes.builtins.ListNodes;
import com.oracle.graal.python.nodes.builtins.ListNodes.ConstructListNode;
Expand Down Expand Up @@ -1730,7 +1731,7 @@ static Object ord(@SuppressWarnings("unused") Object obj,
"flush: whether to forcibly flush the stream.")
@GenerateNodeFactory
public abstract static class PrintNode extends PythonBuiltinNode {
@Child private ReadAttributeFromObjectNode readStdout;
@Child private ReadAttributeFromModuleNode readStdout;
@CompilationFinal private PythonModule cachedSys;

@Specialization
Expand Down Expand Up @@ -1836,7 +1837,7 @@ private Object getStdout() {
}
if (readStdout == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
readStdout = insert(ReadAttributeFromObjectNode.create());
readStdout = insert(ReadAttributeFromModuleNode.create());
}
Object stdout = readStdout.execute(sys, T_STDOUT);
if (stdout == NO_VALUE) {
Expand Down Expand Up @@ -2435,7 +2436,7 @@ protected Object doItNonFunction(VirtualFrame frame, Object function, Object[] a
@Cached CastToTruffleStringNode castToTruffleStringNode,
@Cached("createFor($node)") IndirectCallData indirectCallData,
@Cached CalculateMetaclassNode calculateMetaClass,
@Cached("create(T___PREPARE__)") GetAttributeNode getPrepare,
@Cached("create(T___PREPARE__)") GetFixedAttributeNode getPrepare,
@Cached PyMappingCheckNode pyMappingCheckNode,
@Cached CallNode callPrep,
@Cached CallNode callType,
Expand Down Expand Up @@ -2527,7 +2528,7 @@ class InitializeBuildClass {

Object ns;
try {
Object prep = getPrepare.executeObject(frame, init.meta);
Object prep = getPrepare.execute(frame, init.meta);
ns = callPrep.execute(frame, prep, new Object[]{name, init.bases}, init.mkw);
} catch (PException p) {
p.expectAttributeError(inliningTarget, noAttributeProfile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
import com.oracle.graal.python.nodes.HiddenAttr;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.SpecialAttributeNames;
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
import com.oracle.graal.python.nodes.attributes.GetFixedAttributeNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonClinicBuiltinNode;
Expand Down Expand Up @@ -352,10 +352,10 @@ Object exportSymbol(PBuiltinFunction fun, @SuppressWarnings("unused") PNone name
@Specialization(guards = "isModuleMethod(fun)")
static Object exportSymbol(VirtualFrame frame, Object fun, @SuppressWarnings("unused") PNone name,
@Bind Node inliningTarget,
@Cached("create(T___NAME__)") GetAttributeNode.GetFixedAttributeNode getNameAttributeNode,
@Cached("create(T___NAME__)") GetFixedAttributeNode getNameAttributeNode,
@Cached CastToJavaStringNode castToStringNode,
@Cached PRaiseNode raiseNode) {
Object attrNameValue = getNameAttributeNode.executeObject(frame, fun);
Object attrNameValue = getNameAttributeNode.execute(frame, fun);
String methodName;
try {
methodName = castToStringNode.execute(attrNameValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.List;
import java.util.Objects;

import com.oracle.graal.python.nodes.attributes.ReadAttributeFromModuleNode;
import org.graalvm.collections.EconomicMap;

import com.oracle.graal.python.builtins.Builtin;
Expand Down Expand Up @@ -79,8 +80,7 @@
import com.oracle.graal.python.nodes.HiddenAttr;
import com.oracle.graal.python.nodes.PNodeWithContext;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
import com.oracle.graal.python.nodes.attributes.GetFixedAttributeNode;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.builtins.PythonSenaryBuiltinNode;
Expand Down Expand Up @@ -622,7 +622,7 @@ static Object doSingleContext(
@Specialization(replaces = "doSingleContext")
static Object doRead(
@Bind PythonContext context,
@Cached ReadAttributeFromObjectNode read) {
@Cached ReadAttributeFromModuleNode read) {
PythonModule module = context.lookupBuiltinModule(BuiltinNames.T__SRE);
return read.execute(module, T_MATCH_CONSTRUCTOR);
}
Expand All @@ -643,7 +643,7 @@ abstract static class TRegexSearch extends PythonSenaryBuiltinNode {
protected static final TruffleString T__PATTERN__FALLBACK_COMPILE = tsLiteral("_Pattern__fallback_compile");

@Child private HiddenAttr.ReadNode readCacheNode = HiddenAttr.ReadNode.create();
@Child private GetAttributeNode getFallbackCompileNode;
@Child private GetFixedAttributeNode getFallbackCompileNode;
@Child private CallNode callFallbackCompileNode;
@Child private CallNode callFallbackMethodNode;
@Child private SliceNodes.CreateSliceNode createSliceNode;
Expand All @@ -666,7 +666,7 @@ protected Object doCached(VirtualFrame frame, PythonObject pattern, Object input
@Cached @Shared PyNumberAsSizeNode asSizeNode,
@Cached @Shared PyObjectSizeNode lengthNode,
@CachedLibrary(limit = "1") @Shared InteropLibrary libCompiledRegex,
@Cached("create(method.getMethodName())") GetAttributeNode getFallbackMethodNode,
@Cached("create(method.getMethodName())") GetFixedAttributeNode getFallbackMethodNode,
@Cached @Shared TRegexCallExec tRegexCallExec,
@Cached @Shared CreateMatchFromTRegexResultNode createMatchFromTRegexResultNode) {
int pos = asSizeNode.executeExact(frame, inliningTarget, indexNode.execute(frame, inliningTarget, posArg));
Expand All @@ -686,8 +686,9 @@ protected Object doCached(VirtualFrame frame, PythonObject pattern, Object input
reCheckInputTypeNode.execute(frame, input, tRegexCache.isBinary());

if (fallbackProfile.profile(inliningTarget, libCompiledRegex.isNull(compiledRegex))) {
Object fallbackRegex = getCallFallbackCompileNode().executeWithoutFrame(getGetFallbackCompileNode().executeObject(frame, pattern));
return getCallFallbackMethodNode().executeWithoutFrame(getFallbackMethodNode.executeObject(frame, fallbackRegex), input, pos, endPos);
GetFixedAttributeNode getFixedAttributeNode = getGetFallbackCompileNode();
Object fallbackRegex = getCallFallbackCompileNode().executeWithoutFrame(getFixedAttributeNode.execute(frame, pattern));
return getCallFallbackMethodNode().executeWithoutFrame(getFallbackMethodNode.execute(frame, fallbackRegex), input, pos, endPos);
}

Object truncatedInput = input;
Expand Down Expand Up @@ -716,7 +717,7 @@ protected Object doCachedRegex(VirtualFrame frame, PythonObject pattern, Object
@Cached @Shared PyNumberAsSizeNode asSizeNode,
@Cached @Shared PyObjectSizeNode lengthNode,
@CachedLibrary(limit = "1") @Shared InteropLibrary libCompiledRegex,
@Cached("create(method.getMethodName())") GetAttributeNode getFallbackMethodNode,
@Cached("create(method.getMethodName())") GetFixedAttributeNode getFallbackMethodNode,
@Cached @Shared TRegexCallExec tRegexCallExec,
@Cached @Shared CreateMatchFromTRegexResultNode createMatchFromTRegexResultNode) {
return doCached(frame, pattern, input, posArg, endPosArg, method, mustAdvance, inliningTarget, pattern, cachedMethod, mustAdvance, tRegexCompileNode, tRegexCache,
Expand All @@ -738,7 +739,7 @@ protected Object doDynamic(VirtualFrame frame, PythonObject pattern, Object inpu
@Cached @Shared InlinedConditionProfile fallbackProfile,
@Cached @Shared InlinedConditionProfile truncatingInputProfile,
@CachedLibrary(limit = "1") @Shared InteropLibrary libCompiledRegex,
@Cached("create(method.getMethodName())") GetAttributeNode getFallbackMethodNode,
@Cached("create(method.getMethodName())") GetFixedAttributeNode getFallbackMethodNode,
@Cached @Shared TRegexCallExec tRegexCallExec,
@Cached @Shared CreateMatchFromTRegexResultNode createMatchFromTRegexResultNode) {
TRegexCache tRegexCache = getTRegexCache(pattern);
Expand All @@ -752,10 +753,10 @@ protected TRegexCache getTRegexCache(PythonObject pattern) {
return (TRegexCache) readCacheNode.executeCached(pattern, HiddenAttr.TREGEX_CACHE, null);
}

private GetAttributeNode getGetFallbackCompileNode() {
private GetFixedAttributeNode getGetFallbackCompileNode() {
if (getFallbackCompileNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getFallbackCompileNode = insert(GetAttributeNode.create(T__PATTERN__FALLBACK_COMPILE));
getFallbackCompileNode = insert(GetFixedAttributeNode.create(T__PATTERN__FALLBACK_COMPILE));
}
return getFallbackCompileNode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ Object doWarn(VirtualFrame frame, PythonModule mod, Object message, Object categ
@Bind Node inliningTarget,
@Cached("createFor($node)") IndirectCallData indirectCallData,
@Cached SequenceStorageNodes.GetItemScalarNode getItemScalarNode,
@Cached StringNodes.CastToTruffleStringCheckedNode castToStringChecked,
@Cached StringNodes.CastToTruffleStringChecked1Node castToStringChecked,
@Cached PRaiseNode raiseNode,
@Cached WarningsModuleNode moduleFunctionsNode) {
// warnings_warn_impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1014,19 +1014,19 @@ abstract static class PyObjectSetAttrNode extends PNodeWithContext {

@Specialization
static void doBuiltinClass(PythonBuiltinClass object, TruffleString key, Object value,
@Exclusive @Cached(value = "createForceType()", inline = false) WriteAttributeToObjectNode writeAttrNode) {
@Exclusive @Cached WriteAttributeToObjectNode writeAttrNode) {
writeAttrNode.execute(object, key, value);
}

@Specialization
static void doNativeClass(PythonNativeClass object, TruffleString key, Object value,
@Exclusive @Cached(value = "createForceType()", inline = false) WriteAttributeToObjectNode writeAttrNode) {
@Exclusive @Cached WriteAttributeToObjectNode writeAttrNode) {
writeAttrNode.execute(object, key, value);
}

@Specialization(guards = {"!isPythonBuiltinClass(object)"})
static void doObject(PythonObject object, TruffleString key, Object value,
@Exclusive @Cached(inline = false) WriteAttributeToPythonObjectNode writeAttrToPythonObjectNode) {
@Exclusive @Cached WriteAttributeToPythonObjectNode writeAttrToPythonObjectNode) {
writeAttrToPythonObjectNode.execute(object, key, value);
}
}
Expand Down
Loading