Skip to content

Commit 249c4aa

Browse files
committed
[GR-24060] Implement reverse operations for builtin types closer to how CPython does it.
PullRequest: graalpython/997
2 parents afafe5a + 978578b commit 249c4aa

24 files changed

+1009
-1028
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
import java.util.Arrays;
3131
import java.util.concurrent.ConcurrentHashMap;
3232
import java.util.concurrent.Semaphore;
33-
import com.oracle.graal.python.util.Supplier;
3433
import java.util.logging.Level;
3534

3635
import org.graalvm.options.OptionDescriptors;
3736
import org.graalvm.options.OptionKey;
3837
import org.graalvm.options.OptionValues;
3938

39+
import com.oracle.graal.python.builtins.Builtin;
4040
import com.oracle.graal.python.builtins.Python3Core;
4141
import com.oracle.graal.python.builtins.objects.PEllipsis;
4242
import com.oracle.graal.python.builtins.objects.PNone;
@@ -58,7 +58,9 @@
5858
import com.oracle.graal.python.runtime.exception.PException;
5959
import com.oracle.graal.python.runtime.interop.InteropMap;
6060
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
61+
import com.oracle.graal.python.util.Function;
6162
import com.oracle.graal.python.util.PFunctionArgsFinder;
63+
import com.oracle.graal.python.util.Supplier;
6264
import com.oracle.truffle.api.Assumption;
6365
import com.oracle.truffle.api.CallTarget;
6466
import com.oracle.truffle.api.CompilerAsserts;
@@ -127,7 +129,7 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
127129
public final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Only a single context is active");
128130

129131
private final NodeFactory nodeFactory;
130-
public final ConcurrentHashMap<Class<? extends PythonBuiltinBaseNode>, RootCallTarget> builtinCallTargetCache = new ConcurrentHashMap<>();
132+
private final ConcurrentHashMap<String, RootCallTarget> builtinCallTargetCache = new ConcurrentHashMap<>();
131133

132134
@CompilationFinal(dimensions = 1) private static final Object[] CONTEXT_INSENSITIVE_SINGLETONS = new Object[]{PNone.NONE, PNone.NO_VALUE, PEllipsis.INSTANCE, PNotImplemented.NOT_IMPLEMENTED};
133135

@@ -579,4 +581,8 @@ protected void disposeThread(PythonContext context, Thread thread) {
579581
context.disposeThread(thread);
580582
}
581583

584+
public RootCallTarget getOrComputeBuiltinCallTarget(Builtin builtin, Class<? extends PythonBuiltinBaseNode> nodeClass, Function<Builtin, RootCallTarget> supplier) {
585+
String key = builtin.name() + nodeClass.getName();
586+
return builtinCallTargetCache.computeIfAbsent(key, (k) -> supplier.apply(builtin));
587+
}
582588
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,13 @@
8686
* self argument, set this to true.
8787
*/
8888
boolean declaresExplicitSelf() default false;
89+
90+
/**
91+
* Declares that this builtin needs to reverse the first and second argument it receives. This
92+
* implements the reverse operation wrappers from CPython. This only applies to binary and
93+
* ternary nodes.
94+
*
95+
* @see com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode BuiltinFunctionRootNode
96+
*/
97+
boolean reverseOperation() default false;
8998
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ public void initialize(PythonCore core) {
7474
} else {
7575
declaresExplicitSelf = true;
7676
}
77-
RootCallTarget callTarget = core.getLanguage().builtinCallTargetCache.computeIfAbsent(factory.getNodeClass(),
78-
(b) -> Truffle.getRuntime().createCallTarget(new BuiltinFunctionRootNode(core.getLanguage(), builtin, factory, declaresExplicitSelf)));
77+
RootCallTarget callTarget = core.getLanguage().getOrComputeBuiltinCallTarget(builtin, factory.getNodeClass(),
78+
(b) -> Truffle.getRuntime().createCallTarget(new BuiltinFunctionRootNode(core.getLanguage(), builtin, factory, declaresExplicitSelf, builtin.reverseOperation())));
7979
Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : builtin.doc();
8080
if (builtin.constructsClass().length > 0) {
8181
assert !builtin.isGetter() && !builtin.isSetter() && !builtin.isClassmethod() && !builtin.isStaticmethod();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PythonCextBuiltins.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,17 +2359,17 @@ public boolean visit(Node node) {
23592359
case 1:
23602360
rootNode = new BuiltinFunctionRootNode(lang, unaryBuiltin,
23612361
new MayRaiseNodeFactory<PythonUnaryBuiltinNode>(MayRaiseUnaryNodeGen.create(func, errorResult)),
2362-
true);
2362+
true, false);
23632363
break;
23642364
case 2:
23652365
rootNode = new BuiltinFunctionRootNode(lang, binaryBuiltin,
23662366
new MayRaiseNodeFactory<PythonBinaryBuiltinNode>(MayRaiseBinaryNodeGen.create(func, errorResult)),
2367-
true);
2367+
true, false);
23682368
break;
23692369
case 3:
23702370
rootNode = new BuiltinFunctionRootNode(lang, ternaryBuiltin,
23712371
new MayRaiseNodeFactory<PythonTernaryBuiltinNode>(MayRaiseTernaryNodeGen.create(func, errorResult)),
2372-
true);
2372+
true, false);
23732373
break;
23742374
default:
23752375
break;
@@ -2378,7 +2378,7 @@ public boolean visit(Node node) {
23782378
if (rootNode == null) {
23792379
rootNode = new BuiltinFunctionRootNode(lang, varargsBuiltin,
23802380
new MayRaiseNodeFactory<PythonBuiltinNode>(new MayRaiseNode(func, errorResult)),
2381-
true);
2381+
true, false);
23822382
}
23832383

23842384
return factory().createBuiltinFunction(func.getName(), null, 0, Truffle.getRuntime().createCallTarget(rootNode));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/ArrayBuiltins.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import com.oracle.graal.python.nodes.ErrorMessages;
6161
import com.oracle.graal.python.nodes.SpecialMethodNames;
6262
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
63-
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
6463
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
6564
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
6665
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
@@ -99,21 +98,17 @@ PArray doPArray(PArray left, PArray right,
9998
}
10099
}
101100

101+
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
102102
@Builtin(name = __MUL__, minNumOfPositionalArgs = 2)
103103
@GenerateNodeFactory
104-
abstract static class MulNode extends PythonBuiltinNode {
104+
abstract static class MulNode extends PythonBinaryBuiltinNode {
105105
@Specialization
106106
PArray mul(VirtualFrame frame, PArray self, Object times,
107107
@Cached("create()") SequenceStorageNodes.RepeatNode repeatNode) {
108108
return factory().createArray(repeatNode.execute(frame, self.getSequenceStorage(), times));
109109
}
110110
}
111111

112-
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
113-
@GenerateNodeFactory
114-
abstract static class RMulNode extends MulNode {
115-
}
116-
117112
@Builtin(name = __CONTAINS__, minNumOfPositionalArgs = 2)
118113
@GenerateNodeFactory
119114
abstract static class ContainsNode extends PythonBinaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesBuiltins.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ public Object add(Object self, Object other) {
396396
}
397397
}
398398

399+
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
399400
@Builtin(name = __MUL__, minNumOfPositionalArgs = 2)
400401
@GenerateNodeFactory
401402
public abstract static class MulNode extends PythonBinaryBuiltinNode {
@@ -435,11 +436,6 @@ public Object mul(Object self, Object other) {
435436
}
436437
}
437438

438-
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
439-
@GenerateNodeFactory
440-
public abstract static class RMulNode extends MulNode {
441-
}
442-
443439
@Builtin(name = __REPR__, minNumOfPositionalArgs = 1)
444440
@GenerateNodeFactory
445441
public abstract static class ReprNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,11 @@ public static AbsNode create() {
242242

243243
}
244244

245+
@Builtin(name = __RADD__, minNumOfPositionalArgs = 2)
245246
@Builtin(name = __ADD__, minNumOfPositionalArgs = 2)
246247
@TypeSystemReference(PythonArithmeticTypes.class)
247248
@GenerateNodeFactory
248-
abstract static class AddNode extends PythonBuiltinNode {
249+
abstract static class AddNode extends PythonBinaryBuiltinNode {
249250
@Specialization
250251
PComplex doComplexLong(PComplex left, long right) {
251252
return factory().createComplex(left.getReal() + right, left.getImag());
@@ -274,14 +275,10 @@ PNotImplemented doComplex(Object left, Object right) {
274275
}
275276
}
276277

277-
@GenerateNodeFactory
278-
@Builtin(name = __RADD__, minNumOfPositionalArgs = 2)
279-
abstract static class RAddNode extends AddNode {
280-
}
281-
282-
@GenerateNodeFactory
278+
@Builtin(name = __RTRUEDIV__, minNumOfPositionalArgs = 2, reverseOperation = true)
283279
@Builtin(name = __TRUEDIV__, minNumOfPositionalArgs = 2)
284280
@TypeSystemReference(PythonArithmeticTypes.class)
281+
@GenerateNodeFactory
285282
public abstract static class DivNode extends PythonBinaryBuiltinNode {
286283

287284
public abstract PComplex executeComplex(VirtualFrame frame, Object left, Object right);
@@ -339,19 +336,8 @@ PComplex doComplex(PComplex left, PComplex right,
339336
return factory().createComplex(real, imag);
340337
}
341338

342-
@SuppressWarnings("unused")
343-
@Fallback
344-
PNotImplemented doComplex(Object left, Object right) {
345-
return PNotImplemented.NOT_IMPLEMENTED;
346-
}
347-
}
348-
349-
@GenerateNodeFactory
350-
@Builtin(name = __RTRUEDIV__, minNumOfPositionalArgs = 2)
351-
@TypeSystemReference(PythonArithmeticTypes.class)
352-
abstract static class RDivNode extends PythonBinaryBuiltinNode {
353339
@Specialization
354-
PComplex doComplexDouble(PComplex right, double left) {
340+
PComplex doComplexDouble(double left, PComplex right) {
355341
double oprealSq = right.getReal() * right.getReal();
356342
double opimagSq = right.getImag() * right.getImag();
357343
double twice = 2 * right.getImag() * right.getReal();
@@ -361,7 +347,7 @@ PComplex doComplexDouble(PComplex right, double left) {
361347
}
362348

363349
@Specialization
364-
PComplex doComplexInt(PComplex right, long left) {
350+
PComplex doComplexInt(long left, PComplex right) {
365351
double oprealSq = right.getReal() * right.getReal();
366352
double opimagSq = right.getImag() * right.getImag();
367353
double twice = 2 * right.getImag() * right.getReal();
@@ -371,7 +357,7 @@ PComplex doComplexInt(PComplex right, long left) {
371357
}
372358

373359
@Specialization
374-
PComplex doComplexPInt(PComplex right, PInt left) {
360+
PComplex doComplexPInt(PInt left, PComplex right) {
375361
return doComplexDouble(right, left.doubleValue());
376362
}
377363

@@ -382,6 +368,16 @@ PNotImplemented doComplex(Object left, Object right) {
382368
}
383369
}
384370

371+
@GenerateNodeFactory
372+
@TypeSystemReference(PythonArithmeticTypes.class)
373+
abstract static class RDivNode extends PythonBinaryBuiltinNode {
374+
@SuppressWarnings("unused")
375+
@Fallback
376+
PNotImplemented doComplex(Object left, Object right) {
377+
return PNotImplemented.NOT_IMPLEMENTED;
378+
}
379+
}
380+
385381
@GenerateNodeFactory
386382
@Builtin(name = __DIVMOD__, minNumOfPositionalArgs = 2)
387383
abstract static class DivModNode extends PythonBinaryBuiltinNode {
@@ -394,6 +390,7 @@ PComplex doComplexDouble(Object right, Object left) {
394390
}
395391

396392
@GenerateNodeFactory
393+
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
397394
@Builtin(name = __MUL__, minNumOfPositionalArgs = 2)
398395
@TypeSystemReference(PythonArithmeticTypes.class)
399396
abstract static class MulNode extends PythonBinaryBuiltinNode {
@@ -427,11 +424,7 @@ PNotImplemented doGeneric(Object left, Object right) {
427424
}
428425

429426
@GenerateNodeFactory
430-
@Builtin(name = __RMUL__, minNumOfPositionalArgs = 2)
431-
abstract static class RMulNode extends MulNode {
432-
}
433-
434-
@GenerateNodeFactory
427+
@Builtin(name = __RSUB__, minNumOfPositionalArgs = 2, reverseOperation = true)
435428
@Builtin(name = __SUB__, minNumOfPositionalArgs = 2)
436429
@TypeSystemReference(PythonArithmeticTypes.class)
437430
abstract static class SubNode extends PythonBinaryBuiltinNode {
@@ -450,26 +443,20 @@ PComplex doComplex(PComplex left, long right) {
450443
return factory().createComplex(left.getReal() - right, left.getImag());
451444
}
452445

453-
@SuppressWarnings("unused")
454-
@Fallback
455-
PNotImplemented doComplex(Object left, Object right) {
456-
return PNotImplemented.NOT_IMPLEMENTED;
446+
@Specialization
447+
PComplex doComplexDouble(double left, PComplex right) {
448+
return factory().createComplex(left - right.getReal(), -right.getImag());
457449
}
458-
}
459450

460-
@GenerateNodeFactory
461-
@Builtin(name = __RSUB__, minNumOfPositionalArgs = 2)
462-
abstract static class RSubNode extends SubNode {
463-
@Override
464451
@Specialization
465-
PComplex doComplexDouble(PComplex left, double right) {
466-
return factory().createComplex(right - left.getReal(), -left.getImag());
452+
PComplex doComplex(long left, PComplex right) {
453+
return factory().createComplex(left - right.getReal(), -right.getImag());
467454
}
468455

469-
@Override
470-
@Specialization
471-
PComplex doComplex(PComplex left, long right) {
472-
return factory().createComplex(right - left.getReal(), -left.getImag());
456+
@SuppressWarnings("unused")
457+
@Fallback
458+
PNotImplemented doComplex(Object left, Object right) {
459+
return PNotImplemented.NOT_IMPLEMENTED;
473460
}
474461
}
475462

0 commit comments

Comments
 (0)