Skip to content

Commit 538b167

Browse files
committed
Introduce native wrappers for primitive values.
1 parent a50c767 commit 538b167

File tree

4 files changed

+283
-46
lines changed

4 files changed

+283
-46
lines changed

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6060
import com.oracle.graal.python.builtins.PythonBuiltins;
6161
import com.oracle.graal.python.builtins.modules.TruffleCextBuiltinsFactory.GetByteArrayNodeGen;
62-
import com.oracle.graal.python.builtins.modules.TruffleCextBuiltinsFactory.PNativeToPTypeNodeGen;
6362
import com.oracle.graal.python.builtins.objects.PNone;
6463
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
6564
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
@@ -529,7 +528,7 @@ static class ExternalFunctionNode extends RootNode {
529528
@Child CExtNodes.AllToSulongNode toSulongNode = CExtNodes.AllToSulongNode.create();
530529
@Child CExtNodes.AsPythonObjectNode asPythonObjectNode = CExtNodes.AsPythonObjectNode.create();
531530
@Child private Node isNullNode = Message.IS_NULL.createNode();
532-
@Child private PNativeToPTypeNode fromForeign = PNativeToPTypeNode.create();
531+
@Child private PForeignToPTypeNode fromForeign = PForeignToPTypeNode.create();
533532

534533
public ExternalFunctionNode(PythonLanguage lang, String name, TruffleObject cwrapper, TruffleObject callable) {
535534
super(lang);
@@ -608,18 +607,6 @@ public boolean isCloningAllowed() {
608607
}
609608
}
610609

611-
abstract static class PNativeToPTypeNode extends PForeignToPTypeNode {
612-
613-
@Specialization
614-
protected static Object fromNativeNone(PythonNativeWrapper nativeWrapper) {
615-
return nativeWrapper.getDelegate();
616-
}
617-
618-
public static PNativeToPTypeNode create() {
619-
return PNativeToPTypeNodeGen.create();
620-
}
621-
}
622-
623610
@Builtin(name = "Py_NoValue", fixedNumOfPositionalArgs = 0)
624611
@GenerateNodeFactory
625612
abstract static class Py_NoValue extends PythonBuiltinNode {

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

Lines changed: 120 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,15 @@
5252
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.AsPythonObjectNodeGen;
5353
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.CextUpcallNodeGen;
5454
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetNativeClassNodeGen;
55+
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.MaterializeDelegateNodeGen;
5556
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ObjectUpcallNodeGen;
5657
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToJavaNodeGen;
5758
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToSulongNodeGen;
59+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.ByteNativeWrapper;
60+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.DoubleNativeWrapper;
61+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.IntNativeWrapper;
62+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.LongNativeWrapper;
63+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PrimitiveNativeWrapper;
5864
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper;
5965
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper;
6066
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper;
@@ -98,6 +104,7 @@
98104
import com.oracle.truffle.api.nodes.ExplodeLoop;
99105
import com.oracle.truffle.api.nodes.Node;
100106
import com.oracle.truffle.api.profiles.BranchProfile;
107+
import com.oracle.truffle.api.profiles.ConditionProfile;
101108

102109
public abstract class CExtNodes {
103110

@@ -237,28 +244,31 @@ public abstract static class ToSulongNode extends CExtBaseNode {
237244
* passed from Python into C code need to wrap Strings into PStrings.
238245
*/
239246
@Specialization
240-
Object doString(String str) {
241-
return PythonObjectNativeWrapper.wrap(factory().createString(str));
247+
Object doString(String str,
248+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
249+
return PythonObjectNativeWrapper.wrap(factory().createString(str), noWrapperProfile);
242250
}
243251

244252
@Specialization
245-
Object doBoolean(boolean b) {
246-
return PythonObjectNativeWrapper.wrap(factory().createInt(b));
253+
Object doBoolean(boolean b,
254+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
255+
return PythonObjectNativeWrapper.wrap(factory().createInt(b), noWrapperProfile);
247256
}
248257

249258
@Specialization
250259
Object doInteger(int i) {
251-
return PythonObjectNativeWrapper.wrap(factory().createInt(i));
260+
return IntNativeWrapper.create(i);
252261
}
253262

254263
@Specialization
255264
Object doLong(long l) {
256-
return PythonObjectNativeWrapper.wrap(factory().createInt(l));
265+
return LongNativeWrapper.create(l);
257266
}
258267

259268
@Specialization
260-
Object doDouble(double d) {
261-
return PythonObjectNativeWrapper.wrap(factory().createFloat(d));
269+
Object doDouble(double d,
270+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
271+
return PythonObjectNativeWrapper.wrap(factory().createFloat(d), noWrapperProfile);
262272
}
263273

264274
@Specialization
@@ -278,15 +288,17 @@ Object doPythonClass(PythonClass object) {
278288

279289
@Specialization(guards = {"cachedClass == object.getClass()", "!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, limit = "3")
280290
Object runAbstractObjectCached(PythonAbstractObject object,
291+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
281292
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass) {
282293
assert object != PNone.NO_VALUE;
283-
return PythonObjectNativeWrapper.wrap(CompilerDirectives.castExact(object, cachedClass));
294+
return PythonObjectNativeWrapper.wrap(CompilerDirectives.castExact(object, cachedClass), noWrapperProfile);
284295
}
285296

286297
@Specialization(guards = {"!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, replaces = "runAbstractObjectCached")
287-
Object runAbstractObject(PythonAbstractObject object) {
298+
Object runAbstractObject(PythonAbstractObject object,
299+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
288300
assert object != PNone.NO_VALUE;
289-
return PythonObjectNativeWrapper.wrap(object);
301+
return PythonObjectNativeWrapper.wrap(object, noWrapperProfile);
290302
}
291303

292304
@Specialization(guards = {"isForeignObject(object)", "!isNativeWrapper(object)"})
@@ -326,13 +338,33 @@ public abstract static class AsPythonObjectNode extends CExtBaseNode {
326338

327339
@Child GetClassNode getClassNode;
328340

329-
@Specialization(guards = "object.getClass() == cachedClass", limit = "3")
341+
@Specialization(guards = "!isMaterialized(object)")
342+
byte doByteNativeWrapper(ByteNativeWrapper object) {
343+
return object.getValue();
344+
}
345+
346+
@Specialization(guards = "!isMaterialized(object)")
347+
int doIntNativeWrapper(IntNativeWrapper object) {
348+
return object.getValue();
349+
}
350+
351+
@Specialization(guards = "!isMaterialized(object)")
352+
long doLongNativeWrapper(LongNativeWrapper object) {
353+
return object.getValue();
354+
}
355+
356+
@Specialization(guards = "!isMaterialized(object)")
357+
double doDoubleNativeWrapper(DoubleNativeWrapper object) {
358+
return object.getValue();
359+
}
360+
361+
@Specialization(guards = {"!isPrimitiveNativeWrapper(object)", "object.getClass() == cachedClass"}, limit = "3")
330362
Object doNativeWrapper(PythonNativeWrapper object,
331363
@SuppressWarnings("unused") @Cached("object.getClass()") Class<? extends PythonNativeWrapper> cachedClass) {
332364
return CompilerDirectives.castExact(object, cachedClass).getDelegate();
333365
}
334366

335-
@Specialization(replaces = "doNativeWrapper")
367+
@Specialization(guards = "!isPrimitiveNativeWrapper(object)", replaces = "doNativeWrapper")
336368
Object doNativeWrapperGeneric(PythonNativeWrapper object) {
337369
return object.getDelegate();
338370
}
@@ -377,6 +409,10 @@ Object run(Object obj) {
377409
throw raise(PythonErrorType.SystemError, "invalid object from native: %s", obj);
378410
}
379411

412+
protected static boolean isPrimitiveNativeWrapper(PythonNativeWrapper object) {
413+
return object instanceof PrimitiveNativeWrapper && !isMaterialized((PrimitiveNativeWrapper) object);
414+
}
415+
380416
protected boolean isForeignObject(TruffleObject obj) {
381417
// TODO we could probably also just use 'PGuards.isForeignObject'
382418
if (getClassNode == null) {
@@ -386,6 +422,10 @@ protected boolean isForeignObject(TruffleObject obj) {
386422
return getClassNode.execute(obj) == getCore().lookupType(PythonBuiltinClassType.TruffleObject);
387423
}
388424

425+
protected static boolean isMaterialized(PrimitiveNativeWrapper wrapper) {
426+
return wrapper.getMaterializedObject() != null;
427+
}
428+
389429
@TruffleBoundary
390430
public static Object doSlowPath(PythonCore core, Object object) {
391431
if (object instanceof PythonNativeWrapper) {
@@ -401,6 +441,63 @@ public static AsPythonObjectNode create() {
401441
}
402442
}
403443

444+
/**
445+
* Materializes a primitive value of a primitive native wrapper to ensure pointer equality.
446+
*/
447+
public abstract static class MaterializeDelegateNode extends CExtBaseNode {
448+
449+
public abstract Object execute(PythonNativeWrapper object);
450+
451+
@Child GetClassNode getClassNode;
452+
453+
@Specialization
454+
PInt doByteNativeWrapper(ByteNativeWrapper object) {
455+
PInt materializedInt = factory().createInt(object.getValue());
456+
object.setMaterializedObject(materializedInt);
457+
return materializedInt;
458+
}
459+
460+
@Specialization
461+
PInt doIntNativeWrapper(IntNativeWrapper object) {
462+
PInt materializedInt = factory().createInt(object.getValue());
463+
object.setMaterializedObject(materializedInt);
464+
return materializedInt;
465+
}
466+
467+
@Specialization
468+
PInt doLongNativeWrapper(LongNativeWrapper object) {
469+
PInt materializedInt = factory().createInt(object.getValue());
470+
object.setMaterializedObject(materializedInt);
471+
return materializedInt;
472+
}
473+
474+
@Specialization
475+
PFloat doDoubleNativeWrapper(DoubleNativeWrapper object) {
476+
PFloat materializedInt = factory().createFloat(object.getValue());
477+
object.setMaterializedObject(materializedInt);
478+
return materializedInt;
479+
}
480+
481+
@Specialization(guards = {"!isPrimitiveNativeWrapper(object)", "object.getClass() == cachedClass"}, limit = "3")
482+
Object doNativeWrapper(PythonNativeWrapper object,
483+
@SuppressWarnings("unused") @Cached("object.getClass()") Class<? extends PythonNativeWrapper> cachedClass) {
484+
return CompilerDirectives.castExact(object, cachedClass).getDelegate();
485+
}
486+
487+
@Specialization(guards = "!isPrimitiveNativeWrapper(object)", replaces = "doNativeWrapper")
488+
Object doNativeWrapperGeneric(PythonNativeWrapper object) {
489+
return object.getDelegate();
490+
}
491+
492+
protected static boolean isPrimitiveNativeWrapper(PythonNativeWrapper object) {
493+
return object instanceof PrimitiveNativeWrapper;
494+
}
495+
496+
public static MaterializeDelegateNode create() {
497+
return MaterializeDelegateNodeGen.create();
498+
}
499+
}
500+
404501
/**
405502
* Does the same conversion as the native function {@code to_java}. The node tries to avoid
406503
* calling the native function for resolving native handles.
@@ -925,6 +1022,16 @@ long run(PFloat value) {
9251022
return (long) value.getValue();
9261023
}
9271024

1025+
@Specialization
1026+
long doIntNativeWrapper(IntNativeWrapper object) {
1027+
return object.getValue();
1028+
}
1029+
1030+
@Specialization
1031+
long doLongNativeWrapper(LongNativeWrapper object) {
1032+
return object.getValue();
1033+
}
1034+
9281035
@Specialization
9291036
long run(PythonNativeWrapper value,
9301037
@Cached("create()") AsLong recursive) {

0 commit comments

Comments
 (0)