Skip to content

Commit 81068a5

Browse files
committed
get PyObjectSetItem to inline for the common list case
1 parent 26ad86e commit 81068a5

File tree

4 files changed

+76
-24
lines changed

4 files changed

+76
-24
lines changed

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,9 +1176,10 @@ protected static void doByteSimple(ByteSequenceStorage storage, int idx, byte va
11761176
storage.setByteItemNormalized(idx, value);
11771177
}
11781178

1179+
@InliningCutoff
11791180
@Specialization(replaces = "doByteSimple")
11801181
protected static void doByte(ByteSequenceStorage storage, int idx, Object value,
1181-
@Shared("castToByteNode") @Cached CastToByteNode castToByteNode) {
1182+
@Cached CastToByteNode castToByteNode) {
11821183
// TODO: clean this up, we really might need a frame
11831184
storage.setByteItemNormalized(idx, castToByteNode.execute(null, value));
11841185
}
@@ -1193,6 +1194,7 @@ protected static void doIntL(IntSequenceStorage storage, int idx, long value) th
11931194
storage.setIntItemNormalized(idx, PInt.intValueExact(value));
11941195
}
11951196

1197+
@InliningCutoff
11961198
@Specialization(replaces = "doIntL")
11971199
protected static void doIntLOvf(IntSequenceStorage storage, int idx, long value) {
11981200
try {
@@ -1202,6 +1204,7 @@ protected static void doIntLOvf(IntSequenceStorage storage, int idx, long value)
12021204
}
12031205
}
12041206

1207+
@InliningCutoff
12051208
@Specialization(guards = "!value.isNative()")
12061209
protected static void doInt(IntSequenceStorage storage, int idx, PInt value) {
12071210
try {
@@ -1221,6 +1224,7 @@ protected static void doLong(LongSequenceStorage storage, int idx, int value) {
12211224
storage.setLongItemNormalized(idx, value);
12221225
}
12231226

1227+
@InliningCutoff
12241228
@Specialization(guards = "!value.isNative()")
12251229
protected static void doLong(LongSequenceStorage storage, int idx, PInt value) {
12261230
try {
@@ -1240,11 +1244,34 @@ protected static void doObject(ObjectSequenceStorage storage, int idx, Object va
12401244
storage.setItemNormalized(idx, value);
12411245
}
12421246

1247+
@InliningCutoff
1248+
@Specialization
1249+
protected static void doNative(NativeSequenceStorage storage, int idx, Object value,
1250+
@Cached SetNativeItemScalarNode setItem) {
1251+
setItem.execute(storage, idx, value);
1252+
}
1253+
1254+
@Fallback
1255+
@SuppressWarnings("unused")
1256+
static void doError(SequenceStorage s, int idx, Object item) {
1257+
throw new SequenceStoreException(item);
1258+
}
1259+
1260+
public static SetItemScalarNode create() {
1261+
return SetItemScalarNodeGen.create();
1262+
}
1263+
}
1264+
1265+
@GenerateUncached
1266+
@ImportStatic(SequenceStorageBaseNode.class)
1267+
protected abstract static class SetNativeItemScalarNode extends Node {
1268+
public abstract void execute(NativeSequenceStorage s, int idx, Object value);
1269+
12431270
@Specialization(guards = "isByteStorage(storage)")
12441271
protected static void doNativeByte(NativeSequenceStorage storage, int idx, Object value,
12451272
@Shared("raiseNode") @Cached PRaiseNode raiseNode,
12461273
@Shared("lib") @CachedLibrary(limit = "1") InteropLibrary lib,
1247-
@Shared("castToByteNode") @Cached CastToByteNode castToByteNode) {
1274+
@Cached CastToByteNode castToByteNode) {
12481275
try {
12491276
lib.writeArrayElement(storage.getPtr(), idx, castToByteNode.execute(null, value));
12501277
} catch (UnsupportedMessageException | UnsupportedTypeException | InvalidArrayIndexException e) {
@@ -1264,22 +1291,12 @@ protected static void doNative(NativeSequenceStorage storage, int idx, Object va
12641291
}
12651292
}
12661293

1267-
@Fallback
1268-
@SuppressWarnings("unused")
1269-
static void doError(SequenceStorage s, int idx, Object item) {
1270-
throw new SequenceStoreException(item);
1271-
}
1272-
12731294
private static Object verifyValue(NativeSequenceStorage storage, Object item, VerifyNativeItemNode verifyNativeItemNode) {
12741295
if (verifyNativeItemNode.execute(storage.getElementType(), item)) {
12751296
return item;
12761297
}
12771298
throw new SequenceStoreException(item);
12781299
}
1279-
1280-
public static SetItemScalarNode create() {
1281-
return SetItemScalarNodeGen.create();
1282-
}
12831300
}
12841301

12851302
@GenerateUncached

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage;
122122
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
123123
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorageFactory;
124+
import com.oracle.graal.python.runtime.sequence.storage.SequenceStoreException;
124125
import com.oracle.truffle.api.CompilerDirectives;
125126
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
126127
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
@@ -133,6 +134,7 @@
133134
import com.oracle.truffle.api.dsl.TypeSystemReference;
134135
import com.oracle.truffle.api.frame.VirtualFrame;
135136
import com.oracle.truffle.api.nodes.UnexpectedResultException;
137+
import com.oracle.truffle.api.profiles.BranchProfile;
136138
import com.oracle.truffle.api.profiles.ConditionProfile;
137139
import com.oracle.truffle.api.profiles.ValueProfile;
138140
import com.oracle.truffle.api.strings.TruffleString;
@@ -362,11 +364,6 @@ public Object doListError(VirtualFrame frame, Object self, Object key,
362364
throw raise(TypeError, ErrorMessages.OBJ_INDEX_MUST_BE_INT_OR_SLICES, "list", key);
363365
}
364366

365-
@InliningCutoff
366-
protected static boolean isIndexOrSlice(PyIndexCheckNode indexCheckNode, Object key) {
367-
return indexCheckNode.execute(key) || PGuards.isPSlice(key);
368-
}
369-
370367
protected static SequenceStorageNodes.GetItemNode createGetItemNode() {
371368
return SequenceStorageNodes.GetItemNode.create(NormalizeIndexNode.forList(), (s, f) -> f.createList(s));
372369
}
@@ -382,17 +379,35 @@ public abstract static class SetItemNode extends PythonTernaryBuiltinNode {
382379

383380
private final ConditionProfile generalizedProfile = ConditionProfile.createBinaryProfile();
384381

385-
@Specialization(guards = "indexCheckNode.execute(key) || isPSlice(key)", limit = "1")
382+
@Specialization(guards = {"index >= 0", "index < self.getSequenceStorage().length()"})
383+
protected Object doInBounds(VirtualFrame frame, PList self, int index, Object value,
384+
@Shared("indexCheckNode") @SuppressWarnings("unused") @Cached PyIndexCheckNode indexCheckNode,
385+
@Cached SequenceStorageNodes.SetItemScalarNode setItemNode,
386+
@Shared("setItem") @Cached("createSetItem()") SequenceStorageNodes.SetItemNode fullSetItemNode,
387+
@Cached BranchProfile errorProfile) {
388+
try {
389+
setItemNode.execute(self.getSequenceStorage(), index, value);
390+
} catch (SequenceStoreException e) {
391+
errorProfile.enter();
392+
doGeneric(frame, self, index, value, indexCheckNode, fullSetItemNode);
393+
}
394+
return PNone.NONE;
395+
}
396+
397+
@InliningCutoff
398+
@Specialization(guards = "isIndexOrSlice(indexCheckNode, key)", limit = "1")
386399
public Object doGeneric(VirtualFrame frame, PList primary, Object key, Object value,
387-
@SuppressWarnings("unused") @Cached PyIndexCheckNode indexCheckNode,
388-
@Cached("createSetItem()") SequenceStorageNodes.SetItemNode setItemNode) {
400+
@Shared("indexCheckNode") @SuppressWarnings("unused") @Cached PyIndexCheckNode indexCheckNode,
401+
@Shared("setItem") @Cached("createSetItem()") SequenceStorageNodes.SetItemNode setItemNode) {
389402
updateStorage(primary, setItemNode.execute(frame, primary.getSequenceStorage(), key, value));
390403
return PNone.NONE;
391404
}
392405

406+
@InliningCutoff
393407
@SuppressWarnings("unused")
394-
@Fallback
395-
protected Object doGeneric(Object self, Object key, Object value) {
408+
@Specialization(guards = "!isIndexOrSlice(indexCheckNode, key)", limit = "1")
409+
protected Object doError(Object self, Object key, Object value,
410+
@Shared("indexCheckNode") @SuppressWarnings("unused") @Cached PyIndexCheckNode indexCheckNode) {
396411
throw raise(TypeError, ErrorMessages.OBJ_INDEX_MUST_BE_INT_OR_SLICES, "list", key);
397412
}
398413

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyObjectSetItem.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,17 @@
4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
4444

4545
import com.oracle.graal.python.builtins.objects.PNone;
46+
import com.oracle.graal.python.builtins.objects.list.ListBuiltins;
47+
import com.oracle.graal.python.builtins.objects.list.PList;
4648
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
4749
import com.oracle.graal.python.nodes.ErrorMessages;
50+
import com.oracle.graal.python.nodes.PGuards;
4851
import com.oracle.graal.python.nodes.PRaiseNode;
4952
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
5053
import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
5154
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
5255
import com.oracle.graal.python.nodes.object.GetClassNode;
56+
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
5357
import com.oracle.truffle.api.dsl.Cached;
5458
import com.oracle.truffle.api.dsl.GenerateUncached;
5559
import com.oracle.truffle.api.dsl.ImportStatic;
@@ -62,10 +66,17 @@
6266
* Equivalent to use for PyObject_SetItem.
6367
*/
6468
@GenerateUncached
65-
@ImportStatic(SpecialMethodSlot.class)
69+
@ImportStatic({SpecialMethodSlot.class, PGuards.class})
6670
public abstract class PyObjectSetItem extends Node {
6771
public abstract void execute(Frame frame, Object container, Object index, Object item);
6872

73+
@Specialization(guards = "cannotBeOverriddenForImmutableType(object)")
74+
void doList(VirtualFrame frame, PList object, Object key, Object value,
75+
@Cached ListBuiltins.SetItemNode setItemNode) {
76+
setItemNode.execute(frame, object, key, value);
77+
}
78+
79+
@InliningCutoff
6980
@Specialization
7081
void doWithFrame(VirtualFrame frame, Object primary, Object index, Object value,
7182
@Cached GetClassNode getClassNode,
@@ -79,7 +90,8 @@ void doWithFrame(VirtualFrame frame, Object primary, Object index, Object value,
7990
callSetitem.execute(frame, setitem, primary, index, value);
8091
}
8192

82-
@Specialization(replaces = "doWithFrame")
93+
@InliningCutoff
94+
@Specialization(replaces = {"doWithFrame", "doList"})
8395
void doGeneric(Object primary, Object index, Object value,
8496
@Cached GetClassNode getClassNode,
8597
@Cached(parameters = "SetItem") LookupCallableSlotInMRONode lookupSetitem,

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
@@ -92,6 +92,7 @@
9292
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
9393
import com.oracle.graal.python.builtins.objects.type.PythonClass;
9494
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
95+
import com.oracle.graal.python.lib.PyIndexCheckNode;
9596
import com.oracle.graal.python.nodes.object.GetClassNode;
9697
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
9798
import com.oracle.graal.python.runtime.sequence.PSequence;
@@ -104,6 +105,7 @@
104105
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
105106
import com.oracle.graal.python.util.OverflowException;
106107
import com.oracle.truffle.api.CompilerDirectives;
108+
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
107109
import com.oracle.truffle.api.frame.VirtualFrame;
108110
import com.oracle.truffle.api.interop.InteropLibrary;
109111
import com.oracle.truffle.api.interop.UnsupportedMessageException;
@@ -582,6 +584,7 @@ public static boolean cannotBeOverridden(Object clazz) {
582584
return clazz instanceof PythonBuiltinClassType || clazz instanceof PythonBuiltinClass;
583585
}
584586

587+
@InliningCutoff
585588
public static boolean cannotBeOverridden(Object object, GetClassNode getClassNode) {
586589
Object clazz = getClassNode.execute(object);
587590
return clazz instanceof PythonBuiltinClassType || clazz instanceof PythonBuiltinClass;
@@ -629,4 +632,9 @@ public static boolean isMinusOne(long l) {
629632
public static boolean isAscii(TruffleString str, TruffleString.GetCodeRangeNode getCodeRangeNode) {
630633
return getCodeRangeNode.execute(str, TS_ENCODING) == CodeRange.ASCII;
631634
}
635+
636+
@InliningCutoff
637+
public static boolean isIndexOrSlice(PyIndexCheckNode indexCheckNode, Object key) {
638+
return indexCheckNode.execute(key) || isPSlice(key);
639+
}
632640
}

0 commit comments

Comments
 (0)