Skip to content

Commit 10dd8e2

Browse files
committed
Intrinsify PyNumber_UnaryOp
1 parent 2b0d651 commit 10dd8e2

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

graalpython/com.oracle.graal.python.cext/src/abstract.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ int PyNumber_Check(PyObject *o) {
6565
return 0;
6666
}
6767

68-
UPCALL_ID(PyNumber_UnaryOp);
68+
typedef PyObject *(*unaryop_fun_t)(PyObject *, int32_t);
69+
UPCALL_TYPED_ID(PyNumber_UnaryOp, unaryop_fun_t);
6970
static PyObject * do_unaryop(PyObject *v, UnaryOp unaryop) {
70-
return UPCALL_CEXT_O(_jls_PyNumber_UnaryOp, native_to_java(v), unaryop);
71+
return _jls_PyNumber_UnaryOp(native_to_java(v), (int32_t)unaryop);
7172
}
7273

7374
typedef PyObject *(*binop_fun_t)(PyObject *, PyObject *, int32_t);

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
231231
import com.oracle.graal.python.nodes.expression.InplaceArithmetic;
232232
import com.oracle.graal.python.nodes.expression.LookupAndCallInplaceNode;
233+
import com.oracle.graal.python.nodes.expression.UnaryArithmetic;
233234
import com.oracle.graal.python.nodes.frame.GetCurrentFrameRef;
234235
import com.oracle.graal.python.nodes.function.FunctionRootNode;
235236
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -4077,6 +4078,75 @@ static int doBytes(PBytes bytes,
40774078
}
40784079
}
40794080

4081+
// directly called without landing function
4082+
@Builtin(name = "PyNumber_UnaryOp", minNumOfPositionalArgs = 2)
4083+
@GenerateNodeFactory
4084+
abstract static class PyNumberUnaryOp extends PythonBinaryBuiltinNode {
4085+
static int MAX_CACHE_SIZE = UnaryArithmetic.values().length;
4086+
4087+
@Specialization(guards = {"cachedOp == op", "left.isIntLike()"}, limit = "MAX_CACHE_SIZE")
4088+
static Object doIntLikePrimitiveWrapper(VirtualFrame frame, PrimitiveNativeWrapper left, @SuppressWarnings("unused") int op,
4089+
@Cached("op") @SuppressWarnings("unused") int cachedOp,
4090+
@Cached("createCallNode(op)") LookupAndCallUnaryNode callNode,
4091+
@Cached ToNewRefNode toSulongNode,
4092+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
4093+
@Cached GetNativeNullNode getNativeNullNode) {
4094+
try {
4095+
return toSulongNode.execute(callNode.executeObject(frame, left.getLong()));
4096+
} catch (PException e) {
4097+
transformExceptionToNativeNode.execute(e);
4098+
return toSulongNode.execute(getNativeNullNode.execute());
4099+
}
4100+
}
4101+
4102+
@Specialization(guards = "cachedOp == op", limit = "MAX_CACHE_SIZE", replaces = "doIntLikePrimitiveWrapper")
4103+
static Object doObject(VirtualFrame frame, Object left, @SuppressWarnings("unused") int op,
4104+
@Cached AsPythonObjectNode leftToJava,
4105+
@Cached("op") @SuppressWarnings("unused") int cachedOp,
4106+
@Cached("createCallNode(op)") LookupAndCallUnaryNode callNode,
4107+
@Cached ToNewRefNode toSulongNode,
4108+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
4109+
@Cached GetNativeNullNode getNativeNullNode) {
4110+
// still try to avoid expensive materialization of primitives
4111+
Object result;
4112+
try {
4113+
Object leftValue;
4114+
if (left instanceof PrimitiveNativeWrapper) {
4115+
leftValue = PyNumberBinOp.extract((PrimitiveNativeWrapper) left);
4116+
} else {
4117+
leftValue = leftToJava.execute(left);
4118+
}
4119+
result = callNode.executeObject(frame, leftValue);
4120+
} catch (PException e) {
4121+
transformExceptionToNativeNode.execute(e);
4122+
result = getNativeNullNode.execute();
4123+
}
4124+
return toSulongNode.execute(result);
4125+
}
4126+
4127+
/**
4128+
* This needs to stay in sync with {@code abstract.c: enum e_unaryop}.
4129+
*/
4130+
static LookupAndCallUnaryNode createCallNode(int op) {
4131+
UnaryArithmetic unaryArithmetic;
4132+
switch (op) {
4133+
case 0:
4134+
unaryArithmetic = UnaryArithmetic.Pos;
4135+
break;
4136+
case 1:
4137+
unaryArithmetic = UnaryArithmetic.Neg;
4138+
break;
4139+
case 2:
4140+
unaryArithmetic = UnaryArithmetic.Invert;
4141+
break;
4142+
default:
4143+
throw CompilerDirectives.shouldNotReachHere("invalid unary operator");
4144+
}
4145+
return unaryArithmetic.create();
4146+
}
4147+
}
4148+
4149+
// directly called without landing function
40804150
@Builtin(name = "PyNumber_BinOp", minNumOfPositionalArgs = 3)
40814151
@GenerateNodeFactory
40824152
abstract static class PyNumberBinOp extends PythonTernaryBuiltinNode {
@@ -4186,6 +4256,7 @@ private static BinaryArithmetic getBinaryArithmetic(int op) {
41864256

41874257
}
41884258

4259+
// directly called without landing function
41894260
@Builtin(name = "PyNumber_InPlaceBinOp", minNumOfPositionalArgs = 3)
41904261
@GenerateNodeFactory
41914262
abstract static class PyNumberInPlaceBinOp extends PythonTernaryBuiltinNode {

graalpython/lib-graalpython/python_cext.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -459,18 +459,6 @@ def PyNumber_Check(v):
459459
return _safe_check(v, lambda x: isinstance(int(x), int)) or _safe_check(v, lambda x: isinstance(float(x), float))
460460

461461

462-
@may_raise
463-
def PyNumber_UnaryOp(v, unaryop):
464-
if unaryop == 0:
465-
return +v
466-
elif unaryop == 1:
467-
return -v
468-
elif unaryop == 2:
469-
return ~v
470-
else:
471-
raise SystemError("unknown unary operator (code=%s)" % unaryop)
472-
473-
474462
@may_raise
475463
def PyNumber_Index(v):
476464
if not hasattr(v, "__index__"):

0 commit comments

Comments
 (0)