Skip to content

Commit 6d76962

Browse files
committed
Cache results in 'GetTypeMemberNode'.
1 parent fe77f7b commit 6d76962

File tree

6 files changed

+81
-10
lines changed

6 files changed

+81
-10
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,9 @@ int PyType_Ready(PyTypeObject* cls) {
542542
#undef ADD_METHOD_OR_SLOT
543543
}
544544

545+
UPCALL_ID(PyTruffle_Type_Modified);
545546
void PyType_Modified(PyTypeObject* type) {
546-
// (tfel) I don't think we have to do anything here, since we track MRO
547-
// changes separately, anyway
547+
UPCALL_CEXT_VOID(_jls_PyTruffle_Type_Modified, native_to_java(type), polyglot_from_string(type->tp_name, SRC_CS), native_to_java(type->tp_mro));
548548
}
549549

550550
MUST_INLINE static int valid_identifier(PyObject *s) {

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@
189189
import com.oracle.truffle.api.nodes.RootNode;
190190
import com.oracle.truffle.api.profiles.BranchProfile;
191191
import com.oracle.truffle.api.profiles.ConditionProfile;
192+
import com.oracle.truffle.api.profiles.ValueProfile;
193+
import com.oracle.truffle.api.utilities.CyclicAssumption;
192194

193195
@CoreFunctions(defineModule = "python_cext")
194196
public class TruffleCextBuiltins extends PythonBuiltins {
@@ -2314,7 +2316,7 @@ int add(Object self, @SuppressWarnings("unused") Object o) {
23142316

23152317
@Builtin(name = "PyTruffle_Compute_Mro", fixedNumOfPositionalArgs = 2)
23162318
@GenerateNodeFactory
2317-
@TypeSystemReference(PythonArithmeticTypes.class)
2319+
@TypeSystemReference(PythonTypes.class)
23182320
public abstract static class PyTruffle_Compute_Mro extends PythonBinaryBuiltinNode {
23192321

23202322
@Specialization
@@ -2323,4 +2325,26 @@ Object doIt(PythonNativeObject self, String className) {
23232325
return factory().createTuple(new MroSequenceStorage(className, doSlowPath));
23242326
}
23252327
}
2328+
2329+
@Builtin(name = "PyTruffle_Type_Modified", fixedNumOfPositionalArgs = 3)
2330+
@GenerateNodeFactory
2331+
@TypeSystemReference(PythonTypes.class)
2332+
public abstract static class PyTruffle_Type_Modified extends PythonTernaryBuiltinNode {
2333+
2334+
@Specialization
2335+
Object doIt(PythonNativeClass clazz, String name, PTuple mroTuple,
2336+
@Cached("createClassProfile()") ValueProfile profile) {
2337+
CyclicAssumption nativeClassStableAssumption = getContext().getNativeClassStableAssumption(clazz, false);
2338+
if (nativeClassStableAssumption != null) {
2339+
nativeClassStableAssumption.invalidate("PyType_Modified(\"" + name + "\") called");
2340+
}
2341+
SequenceStorage sequenceStorage = profile.profile(mroTuple.getSequenceStorage());
2342+
if (sequenceStorage instanceof MroSequenceStorage) {
2343+
((MroSequenceStorage) sequenceStorage).lookupChanged();
2344+
} else {
2345+
throw new IllegalStateException("invalid MRO object for native type \"" + name + "\"");
2346+
}
2347+
return PNone.NONE;
2348+
}
2349+
}
23262350
}

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.CextUpcallNodeGen;
5858
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.DirectUpcallNodeGen;
5959
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetNativeClassNodeGen;
60+
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetTypeMemberNodeGen;
6061
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.IsPointerNodeGen;
6162
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.MaterializeDelegateNodeGen;
6263
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ObjectUpcallNodeGen;
@@ -100,6 +101,7 @@
100101
import com.oracle.graal.python.nodes.object.GetClassNode;
101102
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
102103
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
104+
import com.oracle.graal.python.nodes.truffle.PythonTypes;
103105
import com.oracle.graal.python.nodes.util.CastToIndexNode;
104106
import com.oracle.graal.python.runtime.exception.PException;
105107
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -113,6 +115,7 @@
113115
import com.oracle.truffle.api.dsl.ImportStatic;
114116
import com.oracle.truffle.api.dsl.NodeFactory;
115117
import com.oracle.truffle.api.dsl.Specialization;
118+
import com.oracle.truffle.api.dsl.TypeSystemReference;
116119
import com.oracle.truffle.api.frame.VirtualFrame;
117120
import com.oracle.truffle.api.interop.ArityException;
118121
import com.oracle.truffle.api.interop.ForeignAccess;
@@ -1608,24 +1611,32 @@ public static GetObjectDictNode create() {
16081611
}
16091612
}
16101613

1611-
public static class GetTypeMemberNode extends GetNativeDictNode {
1614+
@TypeSystemReference(PythonTypes.class)
1615+
public abstract static class GetTypeMemberNode extends GetNativeDictNode {
16121616
@Child private ToSulongNode toSulong;
16131617
@Child private AsPythonObjectNode toJava;
16141618
@Child private PCallCapiFunction callGetTpDictNode;
16151619
@Child private GetLazyClassNode getNativeClassNode;
16161620

16171621
@CompilationFinal private IsBuiltinClassProfile isTypeProfile;
16181622

1619-
private GetTypeMemberNode(String memberName) {
1623+
protected GetTypeMemberNode(String memberName) {
16201624
String getterFuncName = "get_" + memberName;
16211625
if (!NativeCAPISymbols.isValid(getterFuncName)) {
16221626
throw new IllegalArgumentException("invalid native member getter function " + getterFuncName);
16231627
}
16241628
callGetTpDictNode = PCallCapiFunction.create(getterFuncName);
16251629
}
16261630

1627-
@Override
1628-
public Object execute(Object self) {
1631+
@Specialization(guards = "cachedObj.equals(obj)", limit = "1", assumptions = "getNativeClassStableAssumption(cachedObj)")
1632+
public Object doCached(@SuppressWarnings("unused") PythonNativeClass obj,
1633+
@Cached("obj") @SuppressWarnings("unused") PythonNativeClass cachedObj,
1634+
@Cached("doUncached(obj)") Object result) {
1635+
return result;
1636+
}
1637+
1638+
@Specialization
1639+
public Object doUncached(Object self) {
16291640
if (toSulong == null || toJava == null) {
16301641
CompilerDirectives.transferToInterpreterAndInvalidate();
16311642
toSulong = insert(ToSulongNode.create());
@@ -1635,6 +1646,10 @@ public Object execute(Object self) {
16351646
return toJava.execute(callGetTpDictNode.call(toSulong.execute(self)));
16361647
}
16371648

1649+
protected Assumption getNativeClassStableAssumption(PythonNativeClass clazz) {
1650+
return getContext().getNativeClassStableAssumption(clazz, true).getAssumption();
1651+
}
1652+
16381653
private boolean isNativeTypeObject(Object self) {
16391654
if (getNativeClassNode == null || isTypeProfile == null) {
16401655
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -1654,7 +1669,7 @@ public static Object doSlowPath(Object self, String memberName) {
16541669
}
16551670

16561671
public static GetTypeMemberNode create(String typeMember) {
1657-
return new GetTypeMemberNode(typeMember);
1672+
return GetTypeMemberNodeGen.create(typeMember);
16581673
}
16591674
}
16601675
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,16 @@ public int hashCode() {
8181
// this is important for the default '__hash__' implementation
8282
return Objects.hashCode(object);
8383
}
84+
85+
@Override
86+
public boolean equals(Object obj) {
87+
if (this == obj) {
88+
return true;
89+
}
90+
if (obj == null || getClass() != obj.getClass()) {
91+
return false;
92+
}
93+
PythonAbstractNativeObject other = (PythonAbstractNativeObject) obj;
94+
return Objects.equals(object, other.object);
95+
}
8496
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ private static PythonAbstractClass[] cast(Object[] arr) {
540540

541541
@ImportStatic(SpecialMethodNames.class)
542542
public abstract static class IsSameTypeNode extends PNodeWithContext {
543+
@Child private CExtNodes.PointerCompareNode pointerCompareNode;
543544

544545
protected final boolean fastCheck;
545546

@@ -563,8 +564,14 @@ boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject
563564
}
564565

565566
@Specialization(guards = "!fastCheck")
566-
boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right,
567-
@Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) {
567+
boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right) {
568+
if (doNativeFast(left, right)) {
569+
return true;
570+
}
571+
if (pointerCompareNode == null) {
572+
CompilerDirectives.transferToInterpreterAndInvalidate();
573+
pointerCompareNode = insert(CExtNodes.PointerCompareNode.create(SpecialMethodNames.__EQ__));
574+
}
568575
return pointerCompareNode.execute(left, right);
569576
}
570577

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.oracle.graal.python.PythonLanguage;
4343
import com.oracle.graal.python.builtins.objects.bytes.OpaqueBytes;
4444
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PThreadState;
45+
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
4546
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
4647
import com.oracle.graal.python.builtins.objects.dict.PDict;
4748
import com.oracle.graal.python.builtins.objects.module.PythonModule;
@@ -55,13 +56,15 @@
5556
import com.oracle.truffle.api.Truffle;
5657
import com.oracle.truffle.api.TruffleLanguage;
5758
import com.oracle.truffle.api.TruffleLanguage.Env;
59+
import com.oracle.truffle.api.utilities.CyclicAssumption;
5860

5961
public final class PythonContext {
6062

6163
private final PythonLanguage language;
6264
private PythonModule mainModule;
6365
private final PythonCore core;
6466
private final HashMap<Object, CallTarget> atExitHooks = new HashMap<>();
67+
private final HashMap<PythonNativeClass, CyclicAssumption> nativeClassStableAssumptions = new HashMap<>();
6568
private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L);
6669
private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS);
6770

@@ -340,4 +343,14 @@ public void triggerAsyncActions() {
340343
public void registerAsyncAction(Supplier<AsyncAction> actionSupplier) {
341344
handler.registerAction(actionSupplier);
342345
}
346+
347+
@TruffleBoundary
348+
public CyclicAssumption getNativeClassStableAssumption(PythonNativeClass cls, boolean createOnDemand) {
349+
CyclicAssumption assumption = nativeClassStableAssumptions.get(cls);
350+
if (assumption == null && createOnDemand) {
351+
assumption = new CyclicAssumption("Native class " + cls + " stable");
352+
nativeClassStableAssumptions.put(cls, assumption);
353+
}
354+
return assumption;
355+
}
343356
}

0 commit comments

Comments
 (0)