Skip to content

Commit e1fcfde

Browse files
committed
[GR-12094] Defer materialization of values from primitive native wrappers.
PullRequest: graalpython/234
2 parents 389a174 + a8f39a1 commit e1fcfde

30 files changed

+378
-420
lines changed

graalpython/benchmarks/src/micro/c-magic-iter.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,25 @@
5757
int ci_init(PyObject* self, PyObject* args, PyObject* kwds);
5858
5959
PyObject* ci_iter(PyObject* self) {
60-
return ((NativeCustomIterableObject*)self)->it;
60+
PyObject* result = ((NativeCustomIterableObject*)self)->it;
61+
Py_INCREF(result);
62+
return result;
6163
}
6264
6365
PyObject* cit_iter(PyObject* self) {
66+
Py_INCREF(self);
6467
return self;
6568
}
6669
6770
PyObject* cit_next(PyObject* self) {
6871
NativeCustomIteratorObject* s = (NativeCustomIteratorObject*)self;
69-
return PyLong_FromLongLong(ci_item((PyObject*)(s->obj), (s->pos)++));
72+
return ci_item((PyObject*)(s->obj), (s->pos)++);
7073
}
7174
7275
PyObject* ci_item(PyObject* self, Py_ssize_t i) {
73-
return ((NativeCustomIterableObject*)self)->scale * i;
76+
PyObject* result = PyLong_FromSsize_t(((NativeCustomIterableObject*)self)->scale * i);
77+
Py_INCREF(result);
78+
return result;
7479
}
7580
7681
@@ -177,6 +182,8 @@
177182
};
178183
179184
int ci_init(PyObject* self, PyObject* args, PyObject* kwds) {
185+
Py_XINCREF(args);
186+
Py_XINCREF(kwds);
180187
static char *kwlist[] = {"scale", NULL};
181188
Py_ssize_t n = 0;
182189
@@ -187,7 +194,11 @@
187194
tself->scale = n + 1;
188195
189196
PyObject *argList = PyTuple_New(0);
197+
Py_INCREF(argList);
190198
PyObject *obj = PyObject_CallObject((PyObject *) &CustomIteratorType, argList);
199+
Py_DECREF(argList);
200+
Py_INCREF(obj);
201+
Py_INCREF(tself);
191202
((NativeCustomIteratorObject*)obj)->obj = tself;
192203
tself->it = obj;
193204
@@ -221,6 +232,7 @@
221232
Py_INCREF(&CustomIteratorType);
222233
PyModule_AddObject(m, "NativeCustomIterable", (PyObject *)&CustomIterableType);
223234
PyModule_AddObject(m, "NativeCustomIterator", (PyObject *)&CustomIteratorType);
235+
Py_INCREF(m);
224236
return m;
225237
}
226238

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ uint64_t PyTruffle_Wchar_Size() {
247247
return SIZEOF_WCHAR_T;
248248
}
249249

250-
void* PyObjectHandle_ForJavaObject(void* cobj, unsigned long flags) {
250+
void* PyObjectHandle_ForJavaObject(void* cobj) {
251251
if (truffle_cannot_be_handle(cobj)) {
252252
return truffle_deref_handle_for_managed(cobj);
253253
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ PyTypeObject PyLong_Type = PY_TRUFFLE_TYPE("int", &PyType_Type, Py_TPFLAGS_DEFAU
4747

4848
UPCALL_ID(PyLong_AsPrimitive);
4949
long PyLong_AsLong(PyObject *obj) {
50-
return UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(long), polyglot_from_string("long", SRC_CS));
50+
return UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(long));
5151
}
5252

5353
long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) {
5454
if (obj == NULL) {
5555
PyErr_BadInternalCall();
5656
return -1;
5757
}
58-
long result = UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(long), polyglot_from_string("long", SRC_CS));
58+
long result = UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(long));
5959
*overflow = result == -1L && PyErr_Occurred() != NULL;
6060
return result;
6161
}
@@ -79,7 +79,7 @@ unsigned long PyLong_AsUnsignedLong(PyObject *obj) {
7979
PyErr_BadInternalCall();
8080
return (unsigned long)-1;
8181
}
82-
return (unsigned long) UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 0, sizeof(unsigned long), polyglot_from_string("unsigned long", SRC_CS));
82+
return (unsigned long) UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 0, sizeof(unsigned long));
8383
}
8484
PyObject * PyLong_FromSsize_t(Py_ssize_t n) {
8585
return PyLong_FromLongLong(n);
@@ -90,9 +90,8 @@ PyObject * PyLong_FromDouble(double n) {
9090
return UPCALL_CEXT_O(_jls_PyLong_FromDouble, n);
9191
}
9292

93-
UPCALL_ID(ssize_t);
9493
Py_ssize_t PyLong_AsSsize_t(PyObject *obj) {
95-
return UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(Py_ssize_t), _jls_ssize_t);
94+
return UPCALL_CEXT_L(_jls_PyLong_AsPrimitive, native_to_java(obj), 1, sizeof(Py_ssize_t));
9695
}
9796

9897
PyObject * PyLong_FromVoidPtr(void *p) {

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,40 @@ def compile_module(self, name):
174174
arguments=["PyObject* arg0", "PyObject* arg1"],
175175
cmpfunc=unhandled_error_compare
176176
)
177+
178+
test_PointerEquality_Primitive = CPyExtFunction(
179+
lambda args: True,
180+
lambda: (
181+
(True, lambda arg0, *args: arg0),
182+
(False, lambda arg0, *args: arg0),
183+
(10, lambda arg0, *args: arg0),
184+
(10.0, lambda arg0, *args: arg0),
185+
("ten", lambda arg0, *args: arg0),
186+
),
187+
code="""PyObject* PointerEquality_Primitive(PyObject* pyVal, PyObject* fun) {
188+
PyObject** dummyArray = (PyObject**) malloc(sizeof(PyObject*));
189+
PyObject *arg, *result0;
190+
Py_INCREF(pyVal);
191+
Py_INCREF(fun);
192+
dummyArray[0] = pyVal;
193+
194+
arg = PyTuple_New(1);
195+
PyTuple_SET_ITEM(arg, 0, dummyArray[0]);
196+
Py_INCREF(arg);
197+
result0 = PyObject_Call(fun, arg, NULL);
198+
if (pyVal != result0) {
199+
PyErr_Format(PyExc_ValueError, "%s is not pointer equal: 0x%lx vs. 0x%lx", PyUnicode_AsUTF8(PyObject_Repr(pyVal)), (void*)pyVal, (void*)result0);
200+
return NULL;
201+
}
202+
203+
free(dummyArray);
204+
Py_DECREF(pyVal);
205+
Py_DECREF(fun);
206+
return Py_True;
207+
}
208+
""",
209+
resultspec="O",
210+
argspec="OO",
211+
arguments=["PyObject* pyVal", "PyObject* fun"],
212+
cmpfunc=unhandled_error_compare
213+
)

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
import com.oracle.truffle.api.nodes.RootNode;
172172
import com.oracle.truffle.api.nodes.UnexpectedResultException;
173173
import com.oracle.truffle.api.profiles.ConditionProfile;
174+
import com.oracle.truffle.api.profiles.ValueProfile;
174175
import com.oracle.truffle.api.source.Source;
175176

176177
@CoreFunctions(defineModule = "builtins")
@@ -488,33 +489,37 @@ public Object eval(VirtualFrame frame, String expression, @SuppressWarnings("unu
488489
}
489490

490491
@Specialization
491-
public Object eval(VirtualFrame frame, PCode code, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals) {
492+
public Object eval(VirtualFrame frame, PCode code, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals,
493+
@Cached("createIdentityProfile()") ValueProfile constantCt) {
492494
Frame callerFrame = readCallerFrameNode.executeWith(frame);
493495
PythonObject callerGlobals = PArguments.getGlobals(callerFrame);
494496
PCell[] callerClosure = PArguments.getClosure(callerFrame);
495-
return evalExpression(code, callerGlobals, callerGlobals, callerClosure);
497+
return evalExpression(constantCt.profile(code.getRootCallTarget()), callerGlobals, callerGlobals, callerClosure);
496498
}
497499

498500
@Specialization
499-
public Object eval(VirtualFrame frame, PCode code, PythonObject globals, @SuppressWarnings("unused") PNone locals) {
501+
public Object eval(VirtualFrame frame, PCode code, PythonObject globals, @SuppressWarnings("unused") PNone locals,
502+
@Cached("createIdentityProfile()") ValueProfile constantCt) {
500503
Frame callerFrame = readCallerFrameNode.executeWith(frame);
501504
PCell[] callerClosure = PArguments.getClosure(callerFrame);
502-
return evalExpression(code, globals, globals, callerClosure);
505+
return evalExpression(constantCt.profile(code.getRootCallTarget()), globals, globals, callerClosure);
503506
}
504507

505508
@Specialization
506-
public Object eval(VirtualFrame frame, PCode code, PythonObject globals, PythonObject locals) {
509+
public Object eval(VirtualFrame frame, PCode code, PythonObject globals, PythonObject locals,
510+
@Cached("createIdentityProfile()") ValueProfile constantCt) {
507511
Frame callerFrame = readCallerFrameNode.executeWith(frame);
508512
PCell[] callerClosure = PArguments.getClosure(callerFrame);
509-
return evalExpression(code, globals, locals, callerClosure);
513+
return evalExpression(constantCt.profile(code.getRootCallTarget()), globals, locals, callerClosure);
510514
}
511515

512516
@Specialization
513-
public Object eval(VirtualFrame frame, PCode code, @SuppressWarnings("unused") PNone globals, PythonObject locals) {
517+
public Object eval(VirtualFrame frame, PCode code, @SuppressWarnings("unused") PNone globals, PythonObject locals,
518+
@Cached("createIdentityProfile()") ValueProfile constantCt) {
514519
Frame callerFrame = readCallerFrameNode.executeWith(frame);
515520
PythonObject callerGlobals = PArguments.getGlobals(callerFrame);
516521
PCell[] callerClosure = PArguments.getClosure(callerFrame);
517-
return evalExpression(code, callerGlobals, locals, callerClosure);
522+
return evalExpression(constantCt.profile(code.getRootCallTarget()), callerGlobals, locals, callerClosure);
518523
}
519524

520525
@Specialization
@@ -551,8 +556,8 @@ private byte[] getByteArray(PIBytesLike pByteArray) {
551556
}
552557

553558
@TruffleBoundary
554-
private static Object evalExpression(PCode code, PythonObject globals, PythonObject locals, PCell[] closure) {
555-
return evalNode(code.getRootCallTarget(), globals, locals, closure);
559+
private static Object evalExpression(RootCallTarget ct, PythonObject globals, PythonObject locals, PCell[] closure) {
560+
return evalNode(ct, globals, locals, closure);
556561
}
557562

558563
@TruffleBoundary

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

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -767,15 +767,23 @@ abstract static class NativeBuiltin extends PythonBuiltinNode {
767767
@Child private GetByteArrayNode getByteArrayNode;
768768

769769
protected void transformToNative(PException p) {
770+
NativeBuiltin.transformToNative(getContext(), p);
771+
}
772+
773+
protected static void transformToNative(PythonContext context, PException p) {
770774
p.getExceptionObject().reifyException();
771-
getContext().setCurrentException(p);
775+
context.setCurrentException(p);
772776
}
773777

774778
protected <T> T raiseNative(T defaultValue, PythonBuiltinClassType errType, String fmt, Object... args) {
779+
return NativeBuiltin.raiseNative(this, defaultValue, errType, fmt, args);
780+
}
781+
782+
protected static <T> T raiseNative(PNodeWithContext n, T defaultValue, PythonBuiltinClassType errType, String fmt, Object... args) {
775783
try {
776-
throw raise(errType, fmt, args);
784+
throw n.raise(errType, fmt, args);
777785
} catch (PException p) {
778-
transformToNative(p);
786+
NativeBuiltin.transformToNative(n.getContext(), p);
779787
return defaultValue;
780788
}
781789
}
@@ -881,23 +889,23 @@ protected static String getUTF32Name(int byteorder) {
881889
}
882890
}
883891

884-
@Builtin(name = "TrufflePInt_AsPrimitive", fixedNumOfPositionalArgs = 4)
892+
@Builtin(name = "TrufflePInt_AsPrimitive", fixedNumOfPositionalArgs = 3)
885893
@GenerateNodeFactory
886-
abstract static class TrufflePInt_AsPrimitive extends NativeBuiltin {
894+
abstract static class TrufflePInt_AsPrimitive extends PythonTernaryBuiltinNode {
887895

888-
public abstract Object executeWith(Object o, int signed, long targetTypeSize, String targetTypeName);
896+
public abstract Object executeWith(Object o, int signed, long targetTypeSize);
889897

890-
public abstract long executeLong(Object o, int signed, long targetTypeSize, String targetTypeName);
898+
public abstract long executeLong(Object o, int signed, long targetTypeSize);
891899

892-
public abstract int executeInt(Object o, int signed, long targetTypeSize, String targetTypeName);
900+
public abstract int executeInt(Object o, int signed, long targetTypeSize);
893901

894902
@Specialization(guards = "targetTypeSize == 4")
895-
int doInt4(int obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
903+
int doInt4(int obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize) {
896904
return obj;
897905
}
898906

899907
@Specialization(guards = "targetTypeSize == 8")
900-
long doInt8(int obj, int signed, @SuppressWarnings("unused") long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
908+
long doInt8(int obj, int signed, @SuppressWarnings("unused") long targetTypeSize) {
901909
if (signed != 0) {
902910
return obj;
903911
} else {
@@ -906,32 +914,32 @@ long doInt8(int obj, int signed, @SuppressWarnings("unused") long targetTypeSize
906914
}
907915

908916
@Specialization(guards = {"targetTypeSize != 4", "targetTypeSize != 8"})
909-
int doIntOther(@SuppressWarnings("unused") int obj, @SuppressWarnings("unused") int signed, long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
910-
return raiseNative(-1, PythonErrorType.SystemError, "Unsupported target size: %d", targetTypeSize);
917+
int doIntOther(@SuppressWarnings("unused") int obj, @SuppressWarnings("unused") int signed, long targetTypeSize) {
918+
return raiseUnsupportedSize(targetTypeSize);
911919
}
912920

913921
@Specialization(guards = "targetTypeSize == 4")
914-
int doLong4(@SuppressWarnings("unused") long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize, String targetTypeName) {
915-
return raiseNative(-1, PythonErrorType.OverflowError, "Python int too large to convert to C %s", targetTypeName);
922+
int doLong4(@SuppressWarnings("unused") long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize) {
923+
return raiseTooLarge(targetTypeSize);
916924
}
917925

918926
@Specialization(guards = "targetTypeSize == 8")
919-
long doLong8(long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") int targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
927+
long doLong8(long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") int targetTypeSize) {
920928
return obj;
921929
}
922930

923931
@Specialization(guards = "targetTypeSize == 8")
924-
long doLong8(long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
932+
long doLong8(long obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize) {
925933
return obj;
926934
}
927935

928936
@Specialization(guards = {"targetTypeSize != 4", "targetTypeSize != 8"})
929-
int doPInt(@SuppressWarnings("unused") long obj, @SuppressWarnings("unused") int signed, long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
930-
return raiseNative(-1, PythonErrorType.SystemError, "Unsupported target size: %d", targetTypeSize);
937+
int doPInt(@SuppressWarnings("unused") long obj, @SuppressWarnings("unused") int signed, long targetTypeSize) {
938+
return raiseUnsupportedSize(targetTypeSize);
931939
}
932940

933941
@Specialization(guards = "targetTypeSize == 4")
934-
int doPInt4(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSize, String targetTypeName) {
942+
int doPInt4(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSize) {
935943
try {
936944
if (signed != 0) {
937945
return obj.intValueExact();
@@ -941,12 +949,12 @@ int doPInt4(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSiz
941949
throw new ArithmeticException();
942950
}
943951
} catch (ArithmeticException e) {
944-
return raiseNative(-1, PythonErrorType.OverflowError, "Python int too large to convert to C %s", targetTypeName);
952+
return raiseTooLarge(targetTypeSize);
945953
}
946954
}
947955

948956
@Specialization(guards = "targetTypeSize == 8")
949-
long doPInt8(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSize, String targetTypeName) {
957+
long doPInt8(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSize) {
950958
try {
951959
if (signed != 0) {
952960
return obj.longValueExact();
@@ -956,20 +964,32 @@ long doPInt8(PInt obj, int signed, @SuppressWarnings("unused") long targetTypeSi
956964
throw new ArithmeticException();
957965
}
958966
} catch (ArithmeticException e) {
959-
return raiseNative(-1, PythonErrorType.OverflowError, "Python int too large to convert to C %s", targetTypeName);
967+
return raiseTooLarge(targetTypeSize);
960968
}
961969
}
962970

963971
@Specialization(guards = {"targetTypeSize != 4", "targetTypeSize != 8"})
964-
int doPInt(@SuppressWarnings("unused") PInt obj, @SuppressWarnings("unused") int signed, long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
965-
return raiseNative(-1, PythonErrorType.SystemError, "Unsupported target size: %d", targetTypeSize);
972+
int doPInt(@SuppressWarnings("unused") PInt obj, @SuppressWarnings("unused") int signed, long targetTypeSize) {
973+
return raiseUnsupportedSize(targetTypeSize);
966974
}
967975

968976
@Specialization(guards = {"!isInteger(obj)", "!isPInt(obj)"})
969977
@SuppressWarnings("unused")
970-
int doGeneric(Object obj, boolean signed, int targetTypeSize, String targetTypeName) {
978+
int doGeneric(Object obj, boolean signed, int targetTypeSize) {
971979
return raiseNative(-1, PythonErrorType.TypeError, "an integer is required", obj);
972980
}
981+
982+
private int raiseTooLarge(long targetTypeSize) {
983+
return raiseNative(-1, PythonErrorType.OverflowError, "Python int too large to convert to %s-byte C type", targetTypeSize);
984+
}
985+
986+
private Integer raiseUnsupportedSize(long targetTypeSize) {
987+
return raiseNative(-1, PythonErrorType.SystemError, "Unsupported target size: %d", targetTypeSize);
988+
}
989+
990+
private <T> T raiseNative(T defaultValue, PythonBuiltinClassType errType, String fmt, Object... args) {
991+
return NativeBuiltin.raiseNative(this, defaultValue, errType, fmt, args);
992+
}
973993
}
974994

975995
@Builtin(name = "PyTruffle_Unicode_FromWchar", fixedNumOfPositionalArgs = 3)
@@ -1155,7 +1175,7 @@ public static GetByteArrayNode create() {
11551175

11561176
@Specialization
11571177
byte[] doCArrayWrapper(CByteArrayWrapper o, @SuppressWarnings("unused") long size) {
1158-
return o.getDelegate();
1178+
return o.getByteArray();
11591179
}
11601180

11611181
@Specialization
@@ -1998,9 +2018,9 @@ TruffleObject doPointer(PythonNativeVoidPtr n) {
19982018
long doGeneric(Object n) {
19992019
if (asPrimitiveNode == null) {
20002020
CompilerDirectives.transferToInterpreterAndInvalidate();
2001-
asPrimitiveNode = insert(TrufflePInt_AsPrimitiveFactory.create(null));
2021+
asPrimitiveNode = insert(TrufflePInt_AsPrimitiveFactory.create());
20022022
}
2003-
return asPrimitiveNode.executeLong(n, 0, Long.BYTES, "void*");
2023+
return asPrimitiveNode.executeLong(n, 0, Long.BYTES);
20042024
}
20052025
}
20062026
}

0 commit comments

Comments
 (0)