Skip to content

Commit 6042bdd

Browse files
committed
Use special methods slots for lookups of reversible binary ops
We need to differentiate between builtins that share the same node, so BuiltinMethodDescriptor now also contains the name of the builtin.
1 parent c865567 commit 6042bdd

File tree

7 files changed

+395
-133
lines changed

7 files changed

+395
-133
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinMethodDescriptor.java

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,17 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.function;
4242

43+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
44+
4345
import java.util.Objects;
4446
import java.util.concurrent.ConcurrentHashMap;
4547

4648
import com.oracle.graal.python.builtins.Builtin;
4749
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
50+
import com.oracle.graal.python.builtins.objects.module.ModuleBuiltinsFactory;
51+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory;
4852
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
53+
import com.oracle.graal.python.builtins.objects.type.TypeBuiltinsFactory;
4954
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5055
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
5156
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
@@ -74,6 +79,10 @@ public abstract class BuiltinMethodDescriptor {
7479
*/
7580
private static final ConcurrentHashMap<BuiltinMethodDescriptor, BuiltinMethodDescriptor> CACHE = new ConcurrentHashMap<>();
7681

82+
public static final BuiltinMethodDescriptor OBJ_GET_ATTRIBUTE = get(__GETATTRIBUTE__, ObjectBuiltinsFactory.GetAttributeNodeFactory.getInstance(), PythonBuiltinClassType.PythonObject);
83+
public static final BuiltinMethodDescriptor MODULE_GET_ATTRIBUTE = get(__GETATTRIBUTE__, ModuleBuiltinsFactory.ModuleGetattritbuteNodeFactory.getInstance(), PythonBuiltinClassType.PythonModule);
84+
public static final BuiltinMethodDescriptor TYPE_GET_ATTRIBUTE = get(__GETATTRIBUTE__, TypeBuiltinsFactory.GetattributeNodeFactory.getInstance(), PythonBuiltinClassType.PythonClass);
85+
7786
public static BuiltinMethodDescriptor get(PBuiltinFunction function) {
7887
CompilerAsserts.neverPartOfCompilation();
7988
NodeFactory<? extends PythonBuiltinBaseNode> factory = function.getBuiltinNodeFactory();
@@ -91,22 +100,22 @@ public static BuiltinMethodDescriptor get(PBuiltinFunction function) {
91100
assert enclosing == null;
92101
}
93102

94-
return get(factory, type);
103+
return get(function.getName(), factory, type);
95104
}
96105

97-
public static BuiltinMethodDescriptor get(NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
106+
private static BuiltinMethodDescriptor get(String name, NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
98107
CompilerAsserts.neverPartOfCompilation();
99108
Class<? extends PythonBuiltinBaseNode> nodeClass = factory.getNodeClass();
100109
BuiltinMethodDescriptor result = null;
101110
if (PythonUnaryBuiltinNode.class.isAssignableFrom(nodeClass)) {
102-
result = new UnaryBuiltinDescriptor(factory, type);
103-
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 1 : result.getBuiltinAnnotation().name();
111+
result = new UnaryBuiltinDescriptor(name, factory, type);
112+
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 1 : name;
104113
} else if (PythonBinaryBuiltinNode.class.isAssignableFrom(nodeClass)) {
105-
result = new BinaryBuiltinDescriptor(factory, type);
106-
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 2 : result.getBuiltinAnnotation().name();
114+
result = new BinaryBuiltinDescriptor(name, factory, type);
115+
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 2 : name;
107116
} else if (PythonTernaryBuiltinNode.class.isAssignableFrom(nodeClass)) {
108-
result = new TernaryBuiltinDescriptor(factory, type);
109-
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 3 : result.getBuiltinAnnotation().name();
117+
result = new TernaryBuiltinDescriptor(name, factory, type);
118+
assert result.getBuiltinAnnotation().minNumOfPositionalArgs() <= 3 : name;
110119
}
111120
if (result != null) {
112121
return CACHE.computeIfAbsent(result, x -> x);
@@ -115,7 +124,7 @@ public static BuiltinMethodDescriptor get(NodeFactory<? extends PythonBuiltinBas
115124
}
116125

117126
public static boolean isInstance(Object obj) {
118-
return obj instanceof UnaryBuiltinDescriptor || obj instanceof BinaryBuiltinDescriptor || obj instanceof TernaryBuiltinDescriptor;
127+
return obj instanceof BuiltinMethodDescriptor;
119128
}
120129

121130
private static boolean needsFrame(NodeFactory<? extends PythonBuiltinBaseNode> factory) {
@@ -129,8 +138,12 @@ private static boolean needsFrame(NodeFactory<? extends PythonBuiltinBaseNode> f
129138

130139
private final NodeFactory<? extends PythonBuiltinBaseNode> factory;
131140
private final PythonBuiltinClassType type;
141+
// Name allows us to differentiate between builtins shared for reversible operations, such as
142+
// int.__mul__ and int.__rmul__, which have the same node factory
143+
private final String name;
132144

133-
private BuiltinMethodDescriptor(NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
145+
private BuiltinMethodDescriptor(String name, NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
146+
this.name = name;
134147
this.factory = factory;
135148
this.type = type;
136149
}
@@ -139,33 +152,42 @@ public final NodeFactory<? extends PythonBuiltinBaseNode> getFactory() {
139152
return factory;
140153
}
141154

142-
public Builtin getBuiltinAnnotation() {
155+
public final PythonBuiltinClassType getEnclosingType() {
156+
return type;
157+
}
158+
159+
public final String getName() {
160+
return name;
161+
}
162+
163+
public final Builtin getBuiltinAnnotation() {
143164
return factory.getNodeClass().getAnnotationsByType(Builtin.class)[0];
144165
}
145166

167+
@SuppressWarnings("StringEquality")
146168
@Override
147-
public boolean equals(Object o) {
169+
public final boolean equals(Object o) {
148170
if (this == o) {
149171
return true;
150172
}
151173
if (o == null || getClass() != o.getClass()) {
152174
return false;
153175
}
154176
BuiltinMethodDescriptor that = (BuiltinMethodDescriptor) o;
155-
return factory == that.factory && type == that.type;
177+
return factory == that.factory && type == that.type && name == that.name;
156178
}
157179

158180
@Override
159-
public int hashCode() {
160-
return Objects.hash(factory, type);
181+
public final int hashCode() {
182+
return Objects.hash(factory, type, System.identityHashCode(name));
161183
}
162184

163185
// Note: manually written subclass for each builtin works better with Truffle DSL than one
164186
// generic class that would parametrize the 'factory' field
165187

166188
public static final class UnaryBuiltinDescriptor extends BuiltinMethodDescriptor {
167-
public UnaryBuiltinDescriptor(NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
168-
super(factory, type);
189+
public UnaryBuiltinDescriptor(String name, NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
190+
super(name, factory, type);
169191
}
170192

171193
public PythonUnaryBuiltinNode createNode() {
@@ -174,8 +196,8 @@ public PythonUnaryBuiltinNode createNode() {
174196
}
175197

176198
public static final class BinaryBuiltinDescriptor extends BuiltinMethodDescriptor {
177-
public BinaryBuiltinDescriptor(NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
178-
super(factory, type);
199+
public BinaryBuiltinDescriptor(String name, NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
200+
super(name, factory, type);
179201
}
180202

181203
public PythonBinaryBuiltinNode createNode() {
@@ -184,8 +206,8 @@ public PythonBinaryBuiltinNode createNode() {
184206
}
185207

186208
public static final class TernaryBuiltinDescriptor extends BuiltinMethodDescriptor {
187-
public TernaryBuiltinDescriptor(NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
188-
super(factory, type);
209+
public TernaryBuiltinDescriptor(String name, NodeFactory<? extends PythonBuiltinBaseNode> factory, PythonBuiltinClassType type) {
210+
super(name, factory, type);
189211
}
190212

191213
public PythonTernaryBuiltinNode createNode() {

0 commit comments

Comments
 (0)