Skip to content

Commit 84e176c

Browse files
committed
[GR-31560] Call uncached slot descriptors via call target
PullRequest: graalpython/1815
2 parents 09b7f19 + ea81156 commit 84e176c

File tree

7 files changed

+66
-252
lines changed

7 files changed

+66
-252
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4444
import com.oracle.graal.python.builtins.objects.dict.PDict;
4545
import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis;
46+
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor;
4647
import com.oracle.graal.python.builtins.objects.function.PArguments;
4748
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4849
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
@@ -170,6 +171,14 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
170171
*/
171172
private final ConcurrentHashMap<Object, RootCallTarget> cachedCallTargets = new ConcurrentHashMap<>();
172173

174+
/**
175+
* A map to retrieve call targets of special slot methods for a given BuiltinMethodDescriptor.
176+
* Used to perform uncached calls to slots. The call targets are not directly part of
177+
* descriptors because that would make them specific to a language instance. We want to have
178+
* them global in order to be able to efficiently compare them in guards.
179+
*/
180+
private final ConcurrentHashMap<BuiltinMethodDescriptor, RootCallTarget> descriptorCallTargets = new ConcurrentHashMap<>();
181+
173182
private final Shape emptyShape = Shape.newBuilder().allowImplicitCastIntToDouble(false).allowImplicitCastIntToLong(true).shapeFlags(0).propertyAssumptions(true).build();
174183
@CompilationFinal(dimensions = 1) private final Shape[] builtinTypeInstanceShapes = new Shape[PythonBuiltinClassType.VALUES.length];
175184

@@ -857,4 +866,15 @@ public RootCallTarget createCachedCallTarget(Function<PythonLanguage, RootNode>
857866
public RootCallTarget createCachedCallTarget(Function<PythonLanguage, RootNode> rootNodeFunction, Object... cacheKeys) {
858867
return createCachedCallTarget(rootNodeFunction, Arrays.asList(cacheKeys));
859868
}
869+
870+
public void registerBuiltinDescriptorCallTarget(BuiltinMethodDescriptor descriptor, RootCallTarget callTarget) {
871+
descriptorCallTargets.put(descriptor, callTarget);
872+
}
873+
874+
@TruffleBoundary
875+
public RootCallTarget getDescriptorCallTarget(BuiltinMethodDescriptor descriptor) {
876+
RootCallTarget callTarget = descriptorCallTargets.get(descriptor);
877+
assert callTarget != null : "Missing call target for builtin slot descriptor";
878+
return callTarget;
879+
}
860880
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
import java.util.Map.Entry;
3636

3737
import com.oracle.graal.python.builtins.objects.PNone;
38+
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor;
3839
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
3940
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
41+
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
4042
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
4143
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
4244
import com.oracle.graal.python.util.BiConsumer;
@@ -73,13 +75,26 @@ public void initialize(Python3Core core) {
7375
} else {
7476
declaresExplicitSelf = true;
7577
}
76-
RootCallTarget callTarget = core.getLanguage().createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), factory.getNodeClass(), builtin.name());
78+
RootCallTarget callTarget = core.getLanguage().createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, builtin, factory, declaresExplicitSelf), factory.getNodeClass(),
79+
builtin.name());
80+
if (SpecialMethodSlot.findSpecialSlot(builtin.name()) != null) {
81+
for (PythonBuiltinClassType type : annotation.extendClasses()) {
82+
BuiltinMethodDescriptor descriptor = BuiltinMethodDescriptor.get(factory, type);
83+
if (descriptor != null) {
84+
core.getLanguage().registerBuiltinDescriptorCallTarget(descriptor, callTarget);
85+
}
86+
}
87+
}
7788
Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : builtin.doc();
7889
if (constructsClass != PythonBuiltinClassType.nil) {
7990
assert !builtin.isGetter() && !builtin.isSetter() && !builtin.isClassmethod() && !builtin.isStaticmethod();
8091
// we explicitly do not make these "staticmethods" here, since CPython also doesn't
8192
// for builtin types
8293
PBuiltinFunction newFunc = core.factory().createBuiltinFunction(__NEW__, constructsClass, numDefaults(builtin), callTarget);
94+
BuiltinMethodDescriptor descriptor = BuiltinMethodDescriptor.get(newFunc);
95+
if (descriptor != null) {
96+
core.getLanguage().registerBuiltinDescriptorCallTarget(descriptor, callTarget);
97+
}
8398
PythonBuiltinClass builtinClass = core.lookupType(constructsClass);
8499
builtinClass.setAttributeUnsafe(__NEW__, newFunc);
85100
builtinClass.setAttribute(__DOC__, builtinDoc);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/GenericInvokeNode.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public Assumption needNotPassFrameAssumption() {
102102
* @param arguments - the complete (runtime + user) frame arguments for the call
103103
*/
104104
public final Object execute(VirtualFrame frame, Object callee, Object[] arguments) {
105-
assert frame != null;
106105
return executeInternal(frame, callee, arguments);
107106
}
108107

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/CallBinaryMethodNode.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,19 @@
4343
import com.oracle.graal.python.PythonLanguage;
4444
import com.oracle.graal.python.builtins.objects.PNone;
4545
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor.BinaryBuiltinInfo;
46+
import com.oracle.graal.python.builtins.objects.function.PArguments;
4647
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
4748
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4849
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
4950
import com.oracle.graal.python.nodes.call.CallNode;
51+
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
5052
import com.oracle.graal.python.nodes.call.special.MaybeBindDescriptorNode.BoundDescriptor;
5153
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
5254
import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryBuiltinNode;
5355
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
54-
import com.oracle.graal.python.runtime.PythonContext;
5556
import com.oracle.truffle.api.RootCallTarget;
5657
import com.oracle.truffle.api.dsl.Cached;
57-
import com.oracle.truffle.api.dsl.CachedContext;
58+
import com.oracle.truffle.api.dsl.CachedLanguage;
5859
import com.oracle.truffle.api.dsl.GenerateUncached;
5960
import com.oracle.truffle.api.dsl.ReportPolymorphism.Megamorphic;
6061
import com.oracle.truffle.api.dsl.Specialization;
@@ -94,9 +95,13 @@ Object callSpecialMethodSlotInlined(VirtualFrame frame, @SuppressWarnings("unuse
9495

9596
@Specialization(replaces = "callSpecialMethodSlotInlined")
9697
Object callSpecialMethodSlotCallTarget(VirtualFrame frame, BinaryBuiltinInfo info, Object arg1, Object arg2,
97-
@CachedContext(PythonLanguage.class) PythonContext ctx,
98-
@Cached TruffleBoundaryCallNode.Binary boundaryCallNode) {
99-
return boundaryCallNode.execute(frame, ctx, info, arg1, arg2);
98+
@CachedLanguage PythonLanguage language,
99+
@Cached GenericInvokeNode invokeNode) {
100+
RootCallTarget callTarget = language.getDescriptorCallTarget(info);
101+
Object[] arguments = PArguments.create(2);
102+
PArguments.setArgument(arguments, 0, arg1);
103+
PArguments.setArgument(arguments, 1, arg2);
104+
return invokeNode.execute(frame, callTarget, arguments);
100105
}
101106

102107
@Specialization(guards = {"func == cachedFunc",

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/CallTernaryMethodNode.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,18 @@
4242

4343
import com.oracle.graal.python.PythonLanguage;
4444
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor.TernaryBuiltinInfo;
45+
import com.oracle.graal.python.builtins.objects.function.PArguments;
4546
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
4647
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4748
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
4849
import com.oracle.graal.python.nodes.call.CallNode;
50+
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
4951
import com.oracle.graal.python.nodes.call.special.MaybeBindDescriptorNode.BoundDescriptor;
5052
import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryBuiltinNode;
5153
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
52-
import com.oracle.graal.python.runtime.PythonContext;
5354
import com.oracle.truffle.api.RootCallTarget;
5455
import com.oracle.truffle.api.dsl.Cached;
55-
import com.oracle.truffle.api.dsl.CachedContext;
56+
import com.oracle.truffle.api.dsl.CachedLanguage;
5657
import com.oracle.truffle.api.dsl.GenerateUncached;
5758
import com.oracle.truffle.api.dsl.ReportPolymorphism.Megamorphic;
5859
import com.oracle.truffle.api.dsl.Specialization;
@@ -83,9 +84,14 @@ static Object callSpecialMethodSlotInlined(VirtualFrame frame, @SuppressWarnings
8384

8485
@Specialization(replaces = "callSpecialMethodSlotInlined")
8586
static Object callSpecialMethodSlotCallTarget(VirtualFrame frame, TernaryBuiltinInfo info, Object arg1, Object arg2, Object arg3,
86-
@CachedContext(PythonLanguage.class) PythonContext ctx,
87-
@Cached TruffleBoundaryCallNode.Ternary callNode) {
88-
return callNode.execute(frame, ctx, info, arg1, arg2, arg3);
87+
@CachedLanguage PythonLanguage language,
88+
@Cached GenericInvokeNode invokeNode) {
89+
RootCallTarget callTarget = language.getDescriptorCallTarget(info);
90+
Object[] arguments = PArguments.create(3);
91+
PArguments.setArgument(arguments, 0, arg1);
92+
PArguments.setArgument(arguments, 1, arg2);
93+
PArguments.setArgument(arguments, 2, arg3);
94+
return invokeNode.execute(frame, callTarget, arguments);
8995
}
9096

9197
@Specialization(guards = {"func == cachedFunc", "builtinNode != null", "!isReverse",

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/CallUnaryMethodNode.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,19 @@
4343
import com.oracle.graal.python.PythonLanguage;
4444
import com.oracle.graal.python.builtins.objects.PNone;
4545
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor.UnaryBuiltinInfo;
46+
import com.oracle.graal.python.builtins.objects.function.PArguments;
4647
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
4748
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4849
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
4950
import com.oracle.graal.python.nodes.call.CallNode;
51+
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
5052
import com.oracle.graal.python.nodes.call.special.MaybeBindDescriptorNode.BoundDescriptor;
5153
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
5254
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
53-
import com.oracle.graal.python.runtime.PythonContext;
5455
import com.oracle.graal.python.util.PythonUtils;
5556
import com.oracle.truffle.api.RootCallTarget;
5657
import com.oracle.truffle.api.dsl.Cached;
57-
import com.oracle.truffle.api.dsl.CachedContext;
58+
import com.oracle.truffle.api.dsl.CachedLanguage;
5859
import com.oracle.truffle.api.dsl.GenerateUncached;
5960
import com.oracle.truffle.api.dsl.ReportPolymorphism.Megamorphic;
6061
import com.oracle.truffle.api.dsl.Specialization;
@@ -111,9 +112,12 @@ Object callSpecialMethodSlotInlined(VirtualFrame frame, @SuppressWarnings("unuse
111112

112113
@Specialization(replaces = "callSpecialMethodSlotInlined")
113114
Object callSpecialMethodSlotCallTarget(VirtualFrame frame, UnaryBuiltinInfo info, Object receiver,
114-
@CachedContext(PythonLanguage.class) PythonContext ctx,
115-
@Cached TruffleBoundaryCallNode.Unary callNode) {
116-
return callNode.execute(frame, ctx, info, receiver);
115+
@CachedLanguage PythonLanguage language,
116+
@Cached GenericInvokeNode invokeNode) {
117+
RootCallTarget callTarget = language.getDescriptorCallTarget(info);
118+
Object[] arguments = PArguments.create(1);
119+
PArguments.setArgument(arguments, 0, receiver);
120+
return invokeNode.execute(frame, callTarget, arguments);
117121
}
118122

119123
@Specialization(guards = {"func == cachedFunc",

0 commit comments

Comments
 (0)