Skip to content

Commit 784abee

Browse files
committed
[GR-18395] Don't use guards for all native member types.
PullRequest: graalpython/664
2 parents 11b90ef + 46047ce commit 784abee

File tree

4 files changed

+94
-27
lines changed

4 files changed

+94
-27
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,16 +845,18 @@ public static GetAttrNode create() {
845845
public abstract Object executeWithArgs(VirtualFrame frame, Object primary, String name, Object defaultValue);
846846

847847
@SuppressWarnings("unused")
848-
@Specialization(limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", guards = {"name.equals(cachedName)", "isNoValue(defaultValue)"})
848+
@Specialization(limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", guards = {"stringEquals(cachedName, name, stringProfile)", "isNoValue(defaultValue)"})
849849
public Object getAttrDefault(VirtualFrame frame, Object primary, String name, PNone defaultValue,
850+
@Cached("createBinaryProfile()") ConditionProfile stringProfile,
850851
@Cached("name") String cachedName,
851852
@Cached("create(name)") GetFixedAttributeNode getAttributeNode) {
852853
return getAttributeNode.executeObject(frame, primary);
853854
}
854855

855856
@SuppressWarnings("unused")
856-
@Specialization(limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", guards = {"name.equals(cachedName)", "!isNoValue(defaultValue)"})
857+
@Specialization(limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", guards = {"stringEquals(cachedName, name, stringProfile)", "!isNoValue(defaultValue)"})
857858
Object getAttr(VirtualFrame frame, Object primary, String name, Object defaultValue,
859+
@Cached("createBinaryProfile()") ConditionProfile stringProfile,
858860
@Cached("name") String cachedName,
859861
@Cached("create(name)") GetFixedAttributeNode getAttributeNode,
860862
@Cached("create()") IsBuiltinClassProfile errorProfile) {

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

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,18 +1268,60 @@ public String toString() {
12681268
}
12691269

12701270
@ExportMessage
1271-
protected boolean isMemberReadable(String member,
1272-
@CachedLibrary("this") PythonNativeWrapperLibrary lib,
1273-
@Cached GetLazyClassNode getClassNode,
1274-
@Cached GetNameNode getNameNode) {
1275-
return DynamicObjectNativeWrapper.GP_OBJECT.equals(member) || NativeMemberNames.isValid(member) ||
1276-
ReadObjectNativeMemberNode.isPyDateTimeCAPIType(getNameNode.execute(getClassNode.execute(lib.getDelegate(this))));
1271+
@ImportStatic({PGuards.class, NativeMemberNames.class, DynamicObjectNativeWrapper.class})
1272+
abstract static class IsMemberReadable {
1273+
1274+
@SuppressWarnings("unused")
1275+
@Specialization(guards = {"stringEquals(cachedName, name, stringProfile)", "isValid(cachedName)"})
1276+
static boolean isReadableNativeMembers(PythonObjectNativeWrapper receiver, String name,
1277+
@Cached("createBinaryProfile()") ConditionProfile stringProfile,
1278+
@Cached(value = "name", allowUncached = true) String cachedName) {
1279+
return true;
1280+
}
1281+
1282+
@SuppressWarnings("unused")
1283+
@Specialization(guards = "stringEquals(GP_OBJECT, name, stringProfile)")
1284+
static boolean isReadableCachedGP(PythonObjectNativeWrapper receiver, String name,
1285+
@Cached("createBinaryProfile()") ConditionProfile stringProfile) {
1286+
return true;
1287+
}
1288+
1289+
static boolean isPyTimeMemberReadable(PythonObjectNativeWrapper receiver, PythonNativeWrapperLibrary lib, GetLazyClassNode getClassNode, GetNameNode getNameNode) {
1290+
return ReadObjectNativeMemberNode.isPyDateTimeCAPIType(getNameNode.execute(getClassNode.execute(lib.getDelegate(receiver))));
1291+
}
1292+
1293+
@SuppressWarnings("unused")
1294+
@Specialization(guards = "isPyTimeMemberReadable(receiver, lib, getClassNode, getNameNode)")
1295+
static boolean isReadablePyTime(PythonObjectNativeWrapper receiver, String name,
1296+
@CachedLibrary("receiver") PythonNativeWrapperLibrary lib,
1297+
@Cached GetLazyClassNode getClassNode,
1298+
@Cached GetNameNode getNameNode) {
1299+
return true;
1300+
}
1301+
1302+
@Specialization
1303+
@TruffleBoundary
1304+
static boolean isReadableFallback(PythonObjectNativeWrapper receiver, String name,
1305+
@CachedLibrary("receiver") PythonNativeWrapperLibrary lib,
1306+
@Cached GetLazyClassNode getClassNode,
1307+
@Cached GetNameNode getNameNode) {
1308+
return DynamicObjectNativeWrapper.GP_OBJECT.equals(name) || NativeMemberNames.isValid(name) ||
1309+
ReadObjectNativeMemberNode.isPyDateTimeCAPIType(getNameNode.execute(getClassNode.execute(lib.getDelegate(receiver))));
1310+
}
12771311
}
12781312

12791313
@ExportMessage
1280-
@Override
1281-
public boolean isMemberModifiable(String member) {
1282-
return NativeMemberNames.isValid(member);
1314+
@ImportStatic({PGuards.class, NativeMemberNames.class, DynamicObjectNativeWrapper.class})
1315+
abstract static class IsMemberModifiable {
1316+
1317+
@SuppressWarnings("unused")
1318+
@Specialization(guards = "stringEquals(cachedName, name, stringProfile)")
1319+
static boolean isModifiableCached(PythonObjectNativeWrapper receiver, String name,
1320+
@Cached("createBinaryProfile()") ConditionProfile stringProfile,
1321+
@Cached(value = "name", allowUncached = true) String cachedName,
1322+
@Cached(value = "isValid(name)", allowUncached = true) boolean isValid) {
1323+
return isValid;
1324+
}
12831325
}
12841326
}
12851327

@@ -1398,10 +1440,31 @@ public static PrimitiveNativeWrapper createDouble(double val) {
13981440
return new PrimitiveNativeWrapper(val);
13991441
}
14001442

1401-
@Override
14021443
@ExportMessage
1403-
protected boolean isMemberReadable(String member) {
1404-
return member.equals(DynamicObjectNativeWrapper.GP_OBJECT) || NativeMemberNames.isValid(member);
1444+
@ImportStatic({PGuards.class, NativeMemberNames.class, DynamicObjectNativeWrapper.class})
1445+
abstract static class IsMemberReadable {
1446+
1447+
@SuppressWarnings("unused")
1448+
@Specialization(guards = {"stringEquals(cachedName, name, stringProfile)", "isValid(cachedName)"})
1449+
static boolean isReadableNativeMembers(PrimitiveNativeWrapper receiver, String name,
1450+
@Cached("createBinaryProfile()") ConditionProfile stringProfile,
1451+
@Cached(value = "name", allowUncached = true) String cachedName) {
1452+
return true;
1453+
}
1454+
1455+
@SuppressWarnings("unused")
1456+
@Specialization(guards = "stringEquals(GP_OBJECT, name, stringProfile)")
1457+
static boolean isReadableCachedGP(PrimitiveNativeWrapper receiver, String name,
1458+
@Cached("createBinaryProfile()") ConditionProfile stringProfile) {
1459+
return true;
1460+
}
1461+
1462+
@Specialization
1463+
@TruffleBoundary
1464+
static boolean isReadableFallback(@SuppressWarnings("unused") PrimitiveNativeWrapper receiver, String name) {
1465+
return DynamicObjectNativeWrapper.GP_OBJECT.equals(name) || NativeMemberNames.isValid(name);
1466+
}
1467+
14051468
}
14061469

14071470
@ExportMessage

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

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@
4141
package com.oracle.graal.python.builtins.objects.cext;
4242

4343
import java.lang.reflect.Field;
44+
import java.util.HashSet;
4445

45-
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
46-
import com.oracle.truffle.api.nodes.ExplodeLoop;
47-
import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
46+
import com.oracle.truffle.api.CompilerAsserts;
4847

4948
public final class NativeMemberNames {
5049
public static final String OB_BASE = "ob_base";
@@ -140,28 +139,23 @@ public final class NativeMemberNames {
140139
public static final String SET_USED = "used";
141140
public static final String MMAP_DATA = "data";
142141

143-
@CompilationFinal(dimensions = 1) private static final String[] values;
142+
private static final HashSet<String> values = new HashSet<>();
143+
144144
static {
145145
Field[] declaredFields = NativeMemberNames.class.getDeclaredFields();
146-
values = new String[declaredFields.length - 1]; // omit the values field
147146
for (int i = 0; i < declaredFields.length; i++) {
148147
Field s = declaredFields[i];
149148
if (s.getType() == String.class) {
150149
try {
151-
values[i] = (String) s.get(NativeMemberNames.class);
150+
values.add((String) s.get(NativeMemberNames.class));
152151
} catch (IllegalArgumentException | IllegalAccessException e) {
153152
}
154153
}
155154
}
156155
}
157156

158-
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL)
159157
public static boolean isValid(String name) {
160-
for (int i = 0; i < values.length; i++) {
161-
if (name.equals(values[i])) {
162-
return true;
163-
}
164-
}
165-
return false;
158+
CompilerAsserts.neverPartOfCompilation();
159+
return values.contains(name);
166160
}
167161
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,21 @@
8484
import com.oracle.truffle.api.frame.VirtualFrame;
8585
import com.oracle.truffle.api.interop.TruffleObject;
8686
import com.oracle.truffle.api.nodes.UnexpectedResultException;
87+
import com.oracle.truffle.api.profiles.ConditionProfile;
8788

8889
public abstract class PGuards {
8990

9091
/**
9192
* Specialization guards.
9293
*/
9394

95+
public static boolean stringEquals(String expected, String other, ConditionProfile profile) {
96+
if (profile.profile(expected == other)) {
97+
return true;
98+
}
99+
return expected.equals(other);
100+
}
101+
94102
public static boolean isSameObject(Object left, Object right) {
95103
return left == right;
96104
}

0 commit comments

Comments
 (0)