Skip to content

Commit 32323b8

Browse files
committed
Add nb_power slot
1 parent 4dd47b4 commit 32323b8

38 files changed

Lines changed: 743 additions & 310 deletions

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/Slot.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ enum SlotKind {
135135
nb_true_divide("__truediv__, __rtruediv__"),
136136
/** foo @ bar */
137137
nb_matrix_multiply("__matmul__, __rmatmul__"),
138+
/** foo ** bar */
139+
nb_power("__pow__, __rpow__"),
138140
/** sequence length/size */
139141
sq_length("__len__"),
140142
/** sequence item: read element at index */

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/SlotsMapping.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static String getSlotBaseClass(Slot s) {
5656
case nb_add, nb_subtract, nb_multiply, nb_remainder, nb_divmod, nb_lshift, nb_rshift, nb_and, nb_xor, nb_or,
5757
nb_floor_divide, nb_true_divide, nb_matrix_multiply ->
5858
"TpSlotBinaryOp.TpSlotBinaryOpBuiltin";
59+
case nb_power -> "TpSlotNbPower.TpSlotNbPowerBuiltin";
5960
case sq_concat -> "TpSlotBinaryFunc.TpSlotSqConcat";
6061
case sq_length, mp_length -> "TpSlotLen.TpSlotLenBuiltin" + getSuffix(s.isComplex());
6162
case sq_item, sq_repeat -> "TpSlotSizeArgFun.TpSlotSizeArgFunBuiltin";
@@ -77,6 +78,7 @@ static String getSlotNodeBaseClass(Slot s) {
7778
case nb_add, nb_subtract, nb_multiply, nb_remainder, nb_divmod, nb_lshift, nb_rshift, nb_and, nb_xor, nb_or,
7879
nb_floor_divide, nb_true_divide, nb_matrix_multiply ->
7980
"com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.BinaryOpBuiltinNode";
81+
case nb_power -> "com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode";
8082
case sq_concat -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryFunc.SqConcatBuiltinNode";
8183
case sq_length, mp_length -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotLen.LenBuiltinNode";
8284
case sq_item -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotSizeArgFun.SqItemBuiltinNode";

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tp_slots.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -859,13 +859,12 @@ def __rmatmul__(self, other):
859859
assert 2 % obj == 2
860860
assert divmod(obj, 2) == (1, 1)
861861
assert divmod(2, obj) == (0, 2)
862-
# TODO fix on graalpy
863-
# assert obj ** 2 == 9
864-
# assert 2 ** obj == 8
865-
# assert pow(obj, 2, 2) == 1
866-
# if isinstance(obj.delegate, int): # pow doesn't call __rpow__
867-
# assert pow(2, obj, 2) == 0
868-
# assert pow(2, 2, obj) == 1
862+
assert obj ** 2 == 9
863+
assert 2 ** obj == 8
864+
assert pow(obj, 2, 2) == 1
865+
if isinstance(obj.delegate, int): # pow doesn't call __rpow__
866+
assert pow(2, obj, 2) == 0
867+
assert pow(2, 2, obj) == 1
869868
assert -obj == -3
870869
assert +obj == 3
871870
assert abs(obj) == 3

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

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
172172
import com.oracle.graal.python.lib.PyNumberDivmodNode;
173173
import com.oracle.graal.python.lib.PyNumberIndexNode;
174+
import com.oracle.graal.python.lib.PyNumberPowerNode;
174175
import com.oracle.graal.python.lib.PyObjectAsciiNode;
175176
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
176177
import com.oracle.graal.python.lib.PyObjectDir;
@@ -211,14 +212,10 @@
211212
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
212213
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
213214
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
214-
import com.oracle.graal.python.nodes.call.special.LookupAndCallTernaryNode;
215215
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
216216
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
217217
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
218-
import com.oracle.graal.python.nodes.expression.BinaryArithmetic;
219218
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
220-
import com.oracle.graal.python.nodes.expression.BinaryOpNode;
221-
import com.oracle.graal.python.nodes.expression.TernaryArithmetic;
222219
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
223220
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
224221
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -2119,26 +2116,12 @@ private int getDebuggerSessionCount() {
21192116
@Builtin(name = J_POW, minNumOfPositionalArgs = 2, numOfPositionalOnlyArgs = 0, parameterNames = {"base", "exp", "mod"})
21202117
@GenerateNodeFactory
21212118
public abstract static class PowNode extends PythonTernaryBuiltinNode {
2122-
@NeverDefault
2123-
static BinaryOpNode binaryPow() {
2124-
return BinaryArithmetic.Pow.create();
2125-
}
2126-
2127-
@NeverDefault
2128-
static LookupAndCallTernaryNode ternaryPow() {
2129-
return TernaryArithmetic.Pow.create();
2130-
}
21312119

21322120
@Specialization
2133-
Object binary(VirtualFrame frame, Object x, Object y, @SuppressWarnings("unused") PNone z,
2134-
@Cached("binaryPow()") BinaryOpNode powNode) {
2135-
return powNode.executeObject(frame, x, y);
2136-
}
2137-
2138-
@Specialization(guards = "!isPNone(z)")
21392121
Object ternary(VirtualFrame frame, Object x, Object y, Object z,
2140-
@Cached("ternaryPow()") LookupAndCallTernaryNode powNode) {
2141-
return powNode.execute(frame, x, y, z);
2122+
@Bind("this") Node inliningTarget,
2123+
@Cached PyNumberPowerNode power) {
2124+
return power.execute(frame, inliningTarget, x, y, z);
21422125
}
21432126
}
21442127

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextAbstractBuiltins.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import com.oracle.graal.python.lib.PyNumberIndexNode;
110110
import com.oracle.graal.python.lib.PyNumberLongNode;
111111
import com.oracle.graal.python.lib.PyNumberMultiplyNode;
112+
import com.oracle.graal.python.lib.PyNumberPowerNode;
112113
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
113114
import com.oracle.graal.python.lib.PyObjectGetAttr;
114115
import com.oracle.graal.python.lib.PyObjectGetItem;
@@ -132,7 +133,6 @@
132133
import com.oracle.graal.python.nodes.expression.BinaryOpNode;
133134
import com.oracle.graal.python.nodes.expression.InplaceArithmetic;
134135
import com.oracle.graal.python.nodes.expression.LookupAndCallInplaceNode;
135-
import com.oracle.graal.python.nodes.expression.TernaryArithmetic;
136136
import com.oracle.graal.python.nodes.expression.UnaryArithmetic;
137137
import com.oracle.graal.python.nodes.expression.UnaryOpNode;
138138
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
@@ -452,16 +452,10 @@ abstract static class PyNumber_Power extends CApiTernaryBuiltinNode {
452452
@Child private LookupAndCallTernaryNode callNode;
453453

454454
@Specialization
455-
Object doGeneric(Object o1, Object o2, Object o3) {
456-
return ensureCallNode().execute(null, o1, o2, o3);
457-
}
458-
459-
private LookupAndCallTernaryNode ensureCallNode() {
460-
if (callNode == null) {
461-
CompilerDirectives.transferToInterpreterAndInvalidate();
462-
callNode = insert(TernaryArithmetic.Pow.create());
463-
}
464-
return callNode;
455+
Object doGeneric(Object o1, Object o2, Object o3,
456+
@Bind("this") Node inliningTarget,
457+
@Cached PyNumberPowerNode powerNode) {
458+
return powerNode.execute(null, inliningTarget, o1, o2, o3);
465459
}
466460
}
467461

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/PyProcsWrapper.java

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,21 @@
5151
import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.TransformExceptionToNativeNode;
5252
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5353
import com.oracle.graal.python.builtins.objects.ints.PInt;
54+
import com.oracle.graal.python.builtins.objects.type.TpSlots;
5455
import com.oracle.graal.python.builtins.objects.type.TpSlots.GetCachedTpSlotsNode;
5556
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
5657
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot;
5758
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotManaged;
5859
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryFunc.CallSlotBinaryFuncNode;
59-
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.BinaryOpSlot;
6060
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.CallSlotBinaryOpNode;
61+
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.ReversibleSlot;
6162
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrGet.CallSlotDescrGet;
6263
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrSet.CallSlotDescrSet;
6364
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotGetAttr.CallManagedSlotGetAttrNode;
6465
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotInquiry.CallSlotNbBoolNode;
6566
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotLen.CallSlotLenNode;
6667
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotMpAssSubscript.CallSlotMpAssSubscriptNode;
68+
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotNbPower;
6769
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSetAttr.CallManagedSlotSetAttrNode;
6870
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSizeArgFun.CallSlotSizeArgFun;
6971
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSqAssItem.CallSlotSqAssItemNode;
@@ -300,63 +302,63 @@ protected String getSignature() {
300302

301303
@ExportLibrary(InteropLibrary.class)
302304
public static final class BinaryOpSlotFuncWrapper extends TpSlotWrapper {
303-
private final BinaryOpSlot binaryOp;
305+
private final ReversibleSlot binaryOp;
304306

305-
public BinaryOpSlotFuncWrapper(TpSlotManaged delegate, BinaryOpSlot binaryOp) {
307+
public BinaryOpSlotFuncWrapper(TpSlotManaged delegate, ReversibleSlot binaryOp) {
306308
super(delegate);
307309
this.binaryOp = binaryOp;
308310
}
309311

310312
public static BinaryOpSlotFuncWrapper createAdd(TpSlotManaged delegate) {
311-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_ADD);
313+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_ADD);
312314
}
313315

314316
public static BinaryOpSlotFuncWrapper createSubtract(TpSlotManaged delegate) {
315-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_SUBTRACT);
317+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_SUBTRACT);
316318
}
317319

318320
public static BinaryOpSlotFuncWrapper createMultiply(TpSlotManaged delegate) {
319-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_MULTIPLY);
321+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_MULTIPLY);
320322
}
321323

322324
public static BinaryOpSlotFuncWrapper createRemainder(TpSlotManaged delegate) {
323-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_REMAINDER);
325+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_REMAINDER);
324326
}
325327

326328
public static BinaryOpSlotFuncWrapper createLShift(TpSlotManaged delegate) {
327-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_LSHIFT);
329+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_LSHIFT);
328330
}
329331

330332
public static BinaryOpSlotFuncWrapper createRShift(TpSlotManaged delegate) {
331-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_RSHIFT);
333+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_RSHIFT);
332334
}
333335

334336
public static BinaryOpSlotFuncWrapper createAnd(TpSlotManaged delegate) {
335-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_AND);
337+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_AND);
336338
}
337339

338340
public static BinaryOpSlotFuncWrapper createXor(TpSlotManaged delegate) {
339-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_XOR);
341+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_XOR);
340342
}
341343

342344
public static BinaryOpSlotFuncWrapper createOr(TpSlotManaged delegate) {
343-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_OR);
345+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_OR);
344346
}
345347

346348
public static BinaryOpSlotFuncWrapper createFloorDivide(TpSlotManaged delegate) {
347-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_FLOOR_DIVIDE);
349+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_FLOOR_DIVIDE);
348350
}
349351

350352
public static BinaryOpSlotFuncWrapper createTrueDivide(TpSlotManaged delegate) {
351-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_TRUE_DIVIDE);
353+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_TRUE_DIVIDE);
352354
}
353355

354356
public static BinaryOpSlotFuncWrapper createDivMod(TpSlotManaged delegate) {
355-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_DIVMOD);
357+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_DIVMOD);
356358
}
357359

358360
public static BinaryOpSlotFuncWrapper createMatrixMultiply(TpSlotManaged delegate) {
359-
return new BinaryOpSlotFuncWrapper(delegate, BinaryOpSlot.NB_MATRIX_MULTIPLY);
361+
return new BinaryOpSlotFuncWrapper(delegate, ReversibleSlot.NB_MATRIX_MULTIPLY);
360362
}
361363

362364
@ExportMessage
@@ -745,17 +747,17 @@ protected String getSignature() {
745747
}
746748

747749
@ExportLibrary(InteropLibrary.class)
748-
public static final class TernaryFunctionWrapper extends PyProcsWrapper {
750+
public static final class CallFunctionWrapper extends PyProcsWrapper {
749751

750-
public TernaryFunctionWrapper(Object delegate) {
752+
public CallFunctionWrapper(Object delegate) {
751753
super(delegate);
752754
}
753755

754756
@ExportMessage(name = "execute")
755757
static class Execute {
756758

757759
@Specialization(guards = "arguments.length == 3")
758-
static Object call(TernaryFunctionWrapper self, Object[] arguments,
760+
static Object call(CallFunctionWrapper self, Object[] arguments,
759761
@Bind("this") Node inliningTarget,
760762
@Cached ExecutePositionalStarargsNode posStarargsNode,
761763
@Cached ExpandKeywordStarargsNode expandKwargsNode,
@@ -779,7 +781,7 @@ static Object call(TernaryFunctionWrapper self, Object[] arguments,
779781
Object result = callNode.execute(null, self.getDelegate(), pArgs, kwArgsArray);
780782
return toNativeNode.execute(result);
781783
} catch (Throwable t) {
782-
throw checkThrowableBeforeNative(t, "TernaryFunctionWrapper", self.getDelegate());
784+
throw checkThrowableBeforeNative(t, "CallFunctionWrapper", self.getDelegate());
783785
}
784786
} catch (PException e) {
785787
transformExceptionToNativeNode.execute(inliningTarget, e);
@@ -791,7 +793,7 @@ static Object call(TernaryFunctionWrapper self, Object[] arguments,
791793
}
792794

793795
@Specialization(guards = "arguments.length != 3")
794-
static Object error(@SuppressWarnings("unused") TernaryFunctionWrapper self, Object[] arguments) throws ArityException {
796+
static Object error(@SuppressWarnings("unused") CallFunctionWrapper self, Object[] arguments) throws ArityException {
795797
CompilerDirectives.transferToInterpreterAndInvalidate();
796798
throw ArityException.create(3, 3, arguments.length);
797799
}
@@ -803,6 +805,62 @@ protected String getSignature() {
803805
}
804806
}
805807

808+
@ExportLibrary(InteropLibrary.class)
809+
public static final class NbPowerWrapper extends TpSlotWrapper {
810+
811+
public NbPowerWrapper(TpSlotManaged delegate) {
812+
super(delegate);
813+
}
814+
815+
@Override
816+
public TpSlotWrapper cloneWith(TpSlotManaged slot) {
817+
return new NbPowerWrapper(slot);
818+
}
819+
820+
@ExportMessage
821+
static Object execute(NbPowerWrapper self, Object[] arguments,
822+
@Bind("$node") Node inliningTarget,
823+
@Cached NativeToPythonNode toJavaNode,
824+
@Cached PythonToNativeNewRefNode toNativeNode,
825+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
826+
@Cached GetClassNode vGetClassNode,
827+
@Cached GetClassNode wGetClassNode,
828+
@Cached IsSameTypeNode isSameTypeNode,
829+
@Cached GetCachedTpSlotsNode wGetSlots,
830+
@Cached TpSlotNbPower.CallSlotNbPowerNode callSlot,
831+
@Cached GilNode gil) {
832+
boolean mustRelease = gil.acquire();
833+
CApiTiming.enter();
834+
try {
835+
try {
836+
// convert args
837+
Object v = toJavaNode.execute(arguments[0]);
838+
Object w = toJavaNode.execute(arguments[1]);
839+
Object z = toJavaNode.execute(arguments[2]);
840+
Object vType = vGetClassNode.execute(inliningTarget, v);
841+
Object wType = wGetClassNode.execute(inliningTarget, w);
842+
TpSlots wSlots = wGetSlots.execute(inliningTarget, wType);
843+
boolean sameTypes = isSameTypeNode.execute(inliningTarget, vType, wType);
844+
Object result = callSlot.execute(null, inliningTarget, self.getSlot(), v, vType, w, wSlots.nb_power(), wType, z, sameTypes);
845+
return toNativeNode.execute(result);
846+
} catch (Throwable t) {
847+
throw checkThrowableBeforeNative(t, "NbPowerWrapper", self.getDelegate());
848+
}
849+
} catch (PException e) {
850+
transformExceptionToNativeNode.execute(inliningTarget, e);
851+
return PythonContext.get(gil).getNativeNull();
852+
} finally {
853+
CApiTiming.exit(self.timing);
854+
gil.release(mustRelease);
855+
}
856+
}
857+
858+
@Override
859+
protected String getSignature() {
860+
return "(POINTER,POINTER,POINTER):POINTER";
861+
}
862+
}
863+
806864
@ExportLibrary(InteropLibrary.class)
807865
public static final class RichcmpFunctionWrapper extends PyProcsWrapper {
808866

0 commit comments

Comments
 (0)