Skip to content

Commit 72cb697

Browse files
committed
[GR-21867] Avoid instanceof PythonAbstractClass interface
PullRequest: graalpython/932
2 parents fcbce8e + ca928c7 commit 72cb697

File tree

15 files changed

+156
-87
lines changed

15 files changed

+156
-87
lines changed

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@
6464
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
6565
import com.oracle.truffle.api.dsl.NodeFactory;
6666
import com.oracle.truffle.api.dsl.Specialization;
67+
import com.oracle.truffle.api.interop.InteropLibrary;
6768
import com.oracle.truffle.api.interop.TruffleObject;
69+
import com.oracle.truffle.api.library.CachedLibrary;
6870

6971
@CoreFunctions(defineModule = "java")
7072
public class JavaModuleBuiltins extends PythonBuiltins {
@@ -173,8 +175,10 @@ boolean check(Object object) {
173175
@Builtin(name = "instanceof", minNumOfPositionalArgs = 2)
174176
@GenerateNodeFactory
175177
abstract static class InstanceOfNode extends PythonBinaryBuiltinNode {
176-
@Specialization(guards = {"!isForeignObject(object)", "isForeignObject(klass)"})
177-
boolean check(Object object, TruffleObject klass) {
178+
@Specialization(guards = {"!isForeignObject(object, iLibObject)", "isForeignObject(klass, iLibKlass)"}, limit = "3")
179+
boolean check(Object object, TruffleObject klass,
180+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary iLibObject,
181+
@SuppressWarnings("unused") @CachedLibrary("klass") InteropLibrary iLibKlass) {
178182
Env env = getContext().getEnv();
179183
try {
180184
Object hostKlass = env.asHostObject(klass);
@@ -187,8 +191,10 @@ boolean check(Object object, TruffleObject klass) {
187191
return false;
188192
}
189193

190-
@Specialization(guards = {"isForeignObject(object)", "isForeignObject(klass)"})
191-
boolean checkForeign(Object object, TruffleObject klass) {
194+
@Specialization(guards = {"isForeignObject(object, iLibObject)", "isForeignObject(klass, iLibKlass)"}, limit = "3")
195+
boolean checkForeign(Object object, TruffleObject klass,
196+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary iLibObject,
197+
@SuppressWarnings("unused") @CachedLibrary("klass") InteropLibrary iLibKlass) {
192198
Env env = getContext().getEnv();
193199
try {
194200
Object hostObject = env.asHostObject(object);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,6 @@ public final boolean isIterable(@Shared("thisObject") @Cached GetLazyClassNode g
714714

715715
@ExportMessage
716716
public final boolean isCallable(@Exclusive @Cached LookupInheritedAttributeNode.Dynamic callAttrGetterNode) {
717-
assert !PGuards.isCallable(this) || PGuards.isClass(this);
718717
Object call = callAttrGetterNode.execute(this, __CALL__);
719718
return PGuards.isCallable(call);
720719
}

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

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -446,28 +446,32 @@ static Object doPythonClassUncached(@SuppressWarnings("unused") CExtContext cext
446446
return PythonClassNativeWrapper.wrap(object, getNameNode.execute(object));
447447
}
448448

449-
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
449+
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
450450
static Object runAbstractObjectCached(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
451451
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
452-
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass) {
452+
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass,
453+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
453454
assert object != PNone.NO_VALUE;
454455
return PythonObjectNativeWrapper.wrap(CompilerDirectives.castExact(object, cachedClass), noWrapperProfile);
455456
}
456457

457-
@Specialization(guards = {"!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached")
458+
@Specialization(guards = {"!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached", limit = "3")
458459
static Object runAbstractObject(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
459-
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
460+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
461+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
460462
assert object != PNone.NO_VALUE;
461463
return PythonObjectNativeWrapper.wrap(object, noWrapperProfile);
462464
}
463465

464-
@Specialization(guards = {"isForeignObject(object)", "!isNativeWrapper(object)", "!isNativeNull(object)"})
465-
static Object doForeignObject(@SuppressWarnings("unused") CExtContext cextContext, TruffleObject object) {
466+
@Specialization(guards = {"isForeignObject(object, lib)", "!isNativeWrapper(object)", "!isNativeNull(object)"}, limit = "3")
467+
static Object doForeignObject(@SuppressWarnings("unused") CExtContext cextContext, TruffleObject object,
468+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
466469
return TruffleObjectNativeWrapper.wrap(object);
467470
}
468471

469-
@Specialization(guards = "isFallback(object)")
470-
static Object run(@SuppressWarnings("unused") CExtContext cextContext, Object object) {
472+
@Specialization(guards = "isFallback(object, lib)", limit = "1")
473+
static Object run(@SuppressWarnings("unused") CExtContext cextContext, Object object,
474+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
471475
assert object != null : "Java 'null' cannot be a Sulong value";
472476
assert CApiGuards.isNativeWrapper(object) : "unknown object cannot be a Sulong value";
473477
return object;
@@ -477,9 +481,10 @@ protected static PythonClassNativeWrapper wrapNativeClass(PythonManagedClass obj
477481
return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object));
478482
}
479483

480-
static boolean isFallback(Object object) {
484+
static boolean isFallback(Object object, InteropLibrary lib) {
481485
return !(object instanceof String || object instanceof Boolean || object instanceof Integer || object instanceof Long || object instanceof Double ||
482-
object instanceof PythonNativeNull || object instanceof PythonAbstractObject || (PGuards.isForeignObject(object) && !CApiGuards.isNativeWrapper(object)));
486+
object instanceof PythonNativeNull || object instanceof PythonAbstractObject) &&
487+
!(PGuards.isForeignObject(object, lib) && !CApiGuards.isNativeWrapper(object));
483488
}
484489

485490
protected static boolean isNaN(double d) {
@@ -679,38 +684,42 @@ static Object doPythonClassUncached(@SuppressWarnings("unused") CExtContext cext
679684
return PythonClassNativeWrapper.wrapNewRef(object, getNameNode.execute(object));
680685
}
681686

682-
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
687+
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
683688
static Object runAbstractObjectCached(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
684689
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
685-
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass) {
690+
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass,
691+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
686692
assert object != PNone.NO_VALUE;
687693
return PythonObjectNativeWrapper.wrapNewRef(CompilerDirectives.castExact(object, cachedClass), noWrapperProfile);
688694
}
689695

690-
@Specialization(guards = {"!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached")
696+
@Specialization(guards = {"!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached", limit = "3")
691697
static Object runAbstractObject(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
692-
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
698+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
699+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
693700
assert object != PNone.NO_VALUE;
694701
return PythonObjectNativeWrapper.wrapNewRef(object, noWrapperProfile);
695702
}
696703

697-
@Specialization(guards = {"isForeignObject(object)", "!isNativeWrapper(object)", "!isNativeNull(object)"})
698-
static Object doForeignObject(CExtContext cextContext, TruffleObject object) {
704+
@Specialization(guards = {"isForeignObject(object, lib)", "!isNativeWrapper(object)", "!isNativeNull(object)"}, limit = "3")
705+
static Object doForeignObject(CExtContext cextContext, TruffleObject object,
706+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
699707
// this will always be a new wrapper; it's implicitly always a new reference in any case
700-
return ToSulongNode.doForeignObject(cextContext, object);
708+
return ToSulongNode.doForeignObject(cextContext, object, lib);
701709
}
702710

703-
@Specialization(guards = "isFallback(object)")
704-
static Object run(CExtContext cextContext, Object object) {
705-
return ToSulongNode.run(cextContext, object);
711+
@Specialization(guards = "isFallback(object, lib)", limit = "1")
712+
static Object run(CExtContext cextContext, Object object,
713+
@CachedLibrary("object") InteropLibrary lib) {
714+
return ToSulongNode.run(cextContext, object, lib);
706715
}
707716

708717
protected static PythonClassNativeWrapper wrapNativeClass(PythonManagedClass object) {
709718
return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object));
710719
}
711720

712-
static boolean isFallback(Object object) {
713-
return ToSulongNode.isFallback(object);
721+
static boolean isFallback(Object object, InteropLibrary lib) {
722+
return ToSulongNode.isFallback(object, lib);
714723
}
715724

716725
protected static boolean isNaN(double d) {
@@ -725,7 +734,7 @@ protected static boolean isNaN(double d) {
725734
* ref count of all {@link PythonNativeWrapper} (and subclasses) (but not if they are newly
726735
* created since the ref count is already one in this case). But it does not increase the ref
727736
* count on {@link PythonAbstractNativeObject}.
728-
*
737+
*
729738
* The reason for this behavior is that after the native function returns, one can decrease the
730739
* ref count by one and therefore release any allocated handles that would cause a memory leak.
731740
* This is not necessary for {@link PythonAbstractNativeObject} since they are managed by a weak
@@ -834,38 +843,42 @@ static Object doPythonClassUncached(@SuppressWarnings("unused") CExtContext cext
834843
return PythonClassNativeWrapper.wrapNewRef(object, getNameNode.execute(object));
835844
}
836845

837-
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
846+
@Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, limit = "3")
838847
static Object runAbstractObjectCached(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
839848
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
840-
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass) {
849+
@Cached("object.getClass()") Class<? extends PythonAbstractObject> cachedClass,
850+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
841851
assert object != PNone.NO_VALUE;
842852
return PythonObjectNativeWrapper.wrapNewRef(CompilerDirectives.castExact(object, cachedClass), noWrapperProfile);
843853
}
844854

845-
@Specialization(guards = {"!isClass(object)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached")
855+
@Specialization(guards = {"!isClass(object, lib)", "!isNativeObject(object)", "!isSpecialSingleton(object)"}, replaces = "runAbstractObjectCached", limit = "3")
846856
static Object runAbstractObject(@SuppressWarnings("unused") CExtContext cextContext, PythonAbstractObject object,
847-
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
857+
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile,
858+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
848859
assert object != PNone.NO_VALUE;
849860
return PythonObjectNativeWrapper.wrapNewRef(object, noWrapperProfile);
850861
}
851862

852-
@Specialization(guards = {"isForeignObject(object)", "!isNativeWrapper(object)", "!isNativeNull(object)"})
853-
static Object doForeignObject(CExtContext cextContext, TruffleObject object) {
863+
@Specialization(guards = {"isForeignObject(object, lib)", "!isNativeWrapper(object)", "!isNativeNull(object)"}, limit = "3")
864+
static Object doForeignObject(CExtContext cextContext, TruffleObject object,
865+
@SuppressWarnings("unused") @CachedLibrary("object") InteropLibrary lib) {
854866
// this will always be a new wrapper; it's implicitly always a new reference in any case
855-
return ToSulongNode.doForeignObject(cextContext, object);
867+
return ToSulongNode.doForeignObject(cextContext, object, lib);
856868
}
857869

858-
@Specialization(guards = "isFallback(object)")
859-
static Object run(CExtContext cextContext, Object object) {
860-
return ToSulongNode.run(cextContext, object);
870+
@Specialization(guards = "isFallback(object, lib)", limit = "1")
871+
static Object run(CExtContext cextContext, Object object,
872+
@CachedLibrary("object") InteropLibrary lib) {
873+
return ToSulongNode.run(cextContext, object, lib);
861874
}
862875

863876
protected static PythonClassNativeWrapper wrapNativeClass(PythonManagedClass object) {
864877
return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object));
865878
}
866879

867-
static boolean isFallback(Object object) {
868-
return ToSulongNode.isFallback(object);
880+
static boolean isFallback(Object object, InteropLibrary lib) {
881+
return ToSulongNode.isFallback(object, lib);
869882
}
870883

871884
protected static boolean isNaN(double d) {

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
import com.oracle.truffle.api.dsl.Cached;
5757
import com.oracle.truffle.api.dsl.Specialization;
5858
import com.oracle.truffle.api.interop.InteropLibrary;
59-
import com.oracle.truffle.api.interop.TruffleObject;
6059
import com.oracle.truffle.api.interop.UnknownIdentifierException;
6160
import com.oracle.truffle.api.interop.UnsupportedMessageException;
6261
import com.oracle.truffle.api.interop.UnsupportedTypeException;
@@ -73,11 +72,11 @@ public class TruffleObjectNativeWrapper extends PythonNativeWrapper {
7372
// every 'PyObject *' provides 'ob_base', 'ob_type', and 'ob_refcnt'
7473
@CompilationFinal(dimensions = 1) private static final String[] MEMBERS = {GP_OBJECT, OB_BASE.getMemberName(), OB_TYPE.getMemberName(), OB_REFCNT.getMemberName()};
7574

76-
public TruffleObjectNativeWrapper(TruffleObject foreignObject) {
75+
public TruffleObjectNativeWrapper(Object foreignObject) {
7776
super(foreignObject);
7877
}
7978

80-
public static TruffleObjectNativeWrapper wrap(TruffleObject foreignObject) {
79+
public static TruffleObjectNativeWrapper wrap(Object foreignObject) {
8180
assert !CApiGuards.isNativeWrapper(foreignObject) : "attempting to wrap a native wrapper";
8281
return new TruffleObjectNativeWrapper(foreignObject);
8382
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,7 @@ static ParserState doObject(ParserState stateIn, Object kwds, @SuppressWarnings(
869869
@Cached ExecuteConverterNode executeConverterNode,
870870
@Cached GetLazyClassNode getClassNode,
871871
@Cached IsSubtypeNode isSubtypeNode,
872+
@CachedLibrary(limit = "2") InteropLibrary lib,
872873
@Cached(value = "createTJ(stateIn)", uncached = "getUncachedTJ(stateIn)") CExtToJavaNode typeToJavaNode,
873874
@Cached(value = "createTN(stateIn)", uncached = "getUncachedTN(stateIn)") CExtToNativeNode toNativeNode,
874875
@Shared("writeOutVarNode") @Cached WriteOutVarNode writeOutVarNode,
@@ -880,7 +881,7 @@ static ParserState doObject(ParserState stateIn, Object kwds, @SuppressWarnings(
880881
if (!skipOptionalArg(arg, state.restOptional)) {
881882
Object typeObject = typeToJavaNode.execute(getVaArgNode.execute(varargs, state.outIndex));
882883
state = state.incrementOutIndex();
883-
assert PGuards.isClass(typeObject);
884+
assert PGuards.isClass(typeObject, lib);
884885
if (!isSubtypeNode.execute(getClassNode.execute(arg), (LazyPythonClass) typeObject)) {
885886
raiseNode.raiseIntWithoutFrame(0, TypeError, "expected object of type %s, got %p", typeObject, arg);
886887
throw ParseArgumentsException.raise();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ abstract static class NewNode extends PythonBuiltinNode {
549549
* A foreign function call specializes on the length of the passed arguments. Any
550550
* optimization based on the callee has to happen on the other side.a
551551
*/
552-
@Specialization(guards = {"isForeignObject(callee)", "!isNoValue(callee)", "keywords.length == 0"})
552+
@Specialization(guards = {"isForeignObject(callee, lib)", "!isNoValue(callee)", "keywords.length == 0"})
553553
protected Object doInteropCall(Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
554554
@CachedLibrary(limit = "3") InteropLibrary lib,
555555
@Cached("create()") PTypeToForeignNode toForeignNode,
@@ -586,7 +586,7 @@ public final Object executeWithArgs(VirtualFrame frame, Object callee, Object[]
586586
* A foreign function call specializes on the length of the passed arguments. Any
587587
* optimization based on the callee has to happen on the other side.
588588
*/
589-
@Specialization(guards = {"isForeignObject(callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "3")
589+
@Specialization(guards = {"isForeignObject(callee, lib)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "4")
590590
protected Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
591591
@CachedLibrary("callee") InteropLibrary lib,
592592
@CachedContext(PythonLanguage.class) PythonContext context,

0 commit comments

Comments
 (0)