Skip to content

Commit 32c4009

Browse files
committed
[GR-18035] Performance fixes around Python array.
PullRequest: graalpython/642
2 parents cad245f + f27c75e commit 32c4009

File tree

9 files changed

+311
-30
lines changed

9 files changed

+311
-30
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ private static final String[] initializeCoreFiles() {
202202
"str",
203203
"type",
204204
"_imp",
205+
"array",
205206
"_thread",
206207
"function",
207208
"_functools",

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.graal.python.builtins.objects.PNone;
3939
import com.oracle.graal.python.builtins.objects.array.PArray;
4040
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
41+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
4142
import com.oracle.graal.python.builtins.objects.range.PRange;
4243
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
4344
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
@@ -117,6 +118,10 @@ protected boolean isByteArray(String typeCode) {
117118
return typeCode.charAt(0) == 'b';
118119
}
119120

121+
protected boolean isCharArray(String typeCode) {
122+
return typeCode.charAt(0) == 'B';
123+
}
124+
120125
protected boolean isDoubleArray(String typeCode) {
121126
return typeCode.charAt(0) == 'd';
122127
}
@@ -146,6 +151,14 @@ PArray arrayByteInitializer(VirtualFrame frame, LazyPythonClass cls, @SuppressWa
146151
return factory().createArray(cls, byteArray);
147152
}
148153

154+
@Specialization(guards = "isCharArray(typeCode)")
155+
PArray arrayCharInitializer(LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer,
156+
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode,
157+
@Cached SequenceStorageNodes.ToByteArrayNode toByteArrayNode) {
158+
byte[] byteArray = toByteArrayNode.execute(getSequenceStorageNode.execute(initializer));
159+
return factory().createArray(cls, byteArray);
160+
}
161+
149162
@Specialization(guards = "isIntArray(typeCode)")
150163
PArray arrayIntInitializer(VirtualFrame frame, LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer,
151164
@Cached("create()") GetIteratorNode getIterator,
@@ -238,9 +251,9 @@ PArray arrayDoubleInitializer(VirtualFrame frame, LazyPythonClass cls, @Suppress
238251
@Specialization
239252
@TruffleBoundary
240253
PArray arrayWithObjectInitializer(@SuppressWarnings("unused") LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, Object initializer) {
241-
if (!(isIntArray(typeCode) || isByteArray(typeCode) || isDoubleArray(typeCode))) {
254+
if (!(isIntArray(typeCode) || isByteArray(typeCode) || isDoubleArray(typeCode) || isCharArray(typeCode))) {
242255
// TODO implement support for typecodes: b, B, u, h, H, i, I, l, L, q, Q, f or d
243-
throw raise(ValueError, "bad typecode (must be i, d, b, or l)");
256+
throw raise(ValueError, "bad typecode (must be i, d, b, B, or l)");
244257
}
245258
throw new RuntimeException("Unsupported initializer " + initializer);
246259
}
@@ -259,8 +272,9 @@ private PArray makeEmptyArray(LazyPythonClass cls, char type) {
259272
switch (type) {
260273
case 'c':
261274
case 'b':
275+
return factory().createArray(cls, new byte[0]);
262276
case 'B':
263-
return factory().createArray(cls, new char[0]);
277+
return factory().createArray(cls, new byte[0]);
264278
case 'i':
265279
return factory().createArray(cls, new int[0]);
266280
case 'd':

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
import com.oracle.graal.python.builtins.Builtin;
4949
import com.oracle.graal.python.builtins.CoreFunctions;
50+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5051
import com.oracle.graal.python.builtins.PythonBuiltins;
5152
import com.oracle.graal.python.builtins.objects.PNone;
5253
import com.oracle.graal.python.builtins.objects.str.PString;
@@ -109,6 +110,11 @@ Object type(String name) {
109110
Object type(PString name) {
110111
return get(name.getValue());
111112
}
113+
114+
@Fallback
115+
Object doError(Object object) {
116+
throw raise(PythonBuiltinClassType.TypeError, "unsupported operand '%p'", object);
117+
}
112118
}
113119

114120
@Builtin(name = "add_to_classpath", takesVarArgs = true, doc = "Add all arguments to the classpath.")

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,31 @@
5454
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5555
import com.oracle.graal.python.builtins.PythonBuiltins;
5656
import com.oracle.graal.python.builtins.objects.PNone;
57+
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
5758
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
5859
import com.oracle.graal.python.builtins.objects.function.PFunction;
5960
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
6061
import com.oracle.graal.python.builtins.objects.method.PMethod;
6162
import com.oracle.graal.python.builtins.objects.module.PythonModule;
6263
import com.oracle.graal.python.nodes.SpecialAttributeNames;
6364
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
65+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6466
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
67+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
6568
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
6669
import com.oracle.graal.python.nodes.util.CastToStringNode;
6770
import com.oracle.graal.python.runtime.PythonContext;
6871
import com.oracle.graal.python.runtime.PythonCore;
6972
import com.oracle.graal.python.runtime.exception.PythonErrorType;
73+
import com.oracle.graal.python.runtime.sequence.PSequence;
74+
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
7075
import com.oracle.truffle.api.CompilerDirectives;
7176
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
7277
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7378
import com.oracle.truffle.api.TruffleFile;
7479
import com.oracle.truffle.api.TruffleLanguage.Env;
80+
import com.oracle.truffle.api.dsl.Cached;
81+
import com.oracle.truffle.api.dsl.CachedContext;
7582
import com.oracle.truffle.api.dsl.Fallback;
7683
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7784
import com.oracle.truffle.api.dsl.Specialization;
@@ -91,7 +98,7 @@
9198
@CoreFunctions(defineModule = "polyglot")
9299
public final class PolyglotModuleBuiltins extends PythonBuiltins {
93100
@Override
94-
protected List<com.oracle.truffle.api.dsl.NodeFactory<? extends PythonBuiltinNode>> getNodeFactories() {
101+
protected List<com.oracle.truffle.api.dsl.NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
95102
return PolyglotModuleBuiltinsFactory.getFactories();
96103
}
97104

@@ -554,4 +561,22 @@ boolean keyInfo(Object receiver, long member, String info) {
554561
}
555562
}
556563

564+
@Builtin(name = "storage", minNumOfPositionalArgs = 1)
565+
@GenerateNodeFactory
566+
@TypeSystemReference(PythonArithmeticTypes.class)
567+
public abstract static class StorageNode extends PythonUnaryBuiltinNode {
568+
@Specialization
569+
Object doSequence(PSequence seq,
570+
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode,
571+
@CachedContext(PythonLanguage.class) PythonContext context) {
572+
SequenceStorage storage = getSequenceStorageNode.execute(seq);
573+
return context.getEnv().asGuestValue(storage.getInternalArrayObject());
574+
}
575+
576+
@Fallback
577+
Object doError(Object object) {
578+
throw raise(PythonBuiltinClassType.TypeError, "unsupported operand '%p'", object);
579+
}
580+
}
581+
557582
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/ArrayBuiltins.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@
4949
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5050
import com.oracle.graal.python.builtins.PythonBuiltins;
5151
import com.oracle.graal.python.builtins.objects.PNone;
52+
import com.oracle.graal.python.builtins.objects.array.ArrayBuiltinsFactory.ArrayNoGeneralizationNodeGen;
5253
import com.oracle.graal.python.builtins.objects.common.IndexNodes.NormalizeIndexNode;
5354
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
55+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GenNodeSupplier;
56+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GeneralizationNode;
5457
import com.oracle.graal.python.nodes.SpecialMethodNames;
5558
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5659
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -68,6 +71,7 @@
6871
import com.oracle.truffle.api.dsl.Cached;
6972
import com.oracle.truffle.api.dsl.Fallback;
7073
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
74+
import com.oracle.truffle.api.dsl.GenerateUncached;
7175
import com.oracle.truffle.api.dsl.NodeFactory;
7276
import com.oracle.truffle.api.dsl.Specialization;
7377
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -311,4 +315,39 @@ public int len(PArray self) {
311315
return self.len();
312316
}
313317
}
318+
319+
/**
320+
* Does not allow any generalization but compatible types.
321+
*/
322+
@GenerateUncached
323+
public abstract static class ArrayNoGeneralizationNode extends SequenceStorageNodes.NoGeneralizationNode {
324+
325+
public static final GenNodeSupplier SUPPLIER = new GenNodeSupplier() {
326+
327+
public GeneralizationNode create() {
328+
return ArrayNoGeneralizationNodeGen.create();
329+
}
330+
331+
public GeneralizationNode getUncached() {
332+
return ArrayNoGeneralizationNodeGen.getUncached();
333+
}
334+
};
335+
336+
@Override
337+
protected String getErrorMessage() {
338+
return "signed short integer is greater than maximum";
339+
}
340+
}
341+
342+
@Builtin(name = "append", minNumOfPositionalArgs = 2)
343+
@GenerateNodeFactory
344+
public abstract static class ArrayAppendNode extends PythonBinaryBuiltinNode {
345+
@Specialization
346+
PArray append(PArray array, Object arg,
347+
@Cached SequenceStorageNodes.AppendNode appendNode) {
348+
appendNode.execute(array.getSequenceStorage(), arg, ArrayNoGeneralizationNode.SUPPLIER);
349+
return array;
350+
}
351+
}
352+
314353
}

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
110110
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
111111
import com.oracle.truffle.api.dsl.Cached;
112+
import com.oracle.truffle.api.dsl.Cached.Exclusive;
112113
import com.oracle.truffle.api.dsl.Cached.Shared;
113114
import com.oracle.truffle.api.dsl.Fallback;
114115
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -1167,30 +1168,34 @@ Object doEmptyStorage(VirtualFrame frame, EmptyStorage storage, Object key) {
11671168
// this is just a minor performance optimization
11681169
@Specialization
11691170
static Object doPythonObjectString(PythonObjectDictStorage storage, String key,
1170-
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1171-
return doDynamicObjectString(storage, key, readKey);
1171+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey,
1172+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile profile) {
1173+
return doDynamicObjectString(storage, key, readKey, profile);
11721174
}
11731175

11741176
// this is just a minor performance optimization
11751177
@Specialization
11761178
static Object doPythonObjectPString(PythonObjectDictStorage storage, PString key,
1177-
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1178-
return doDynamicObjectPString(storage, key, readKey);
1179+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey,
1180+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile profile) {
1181+
return doDynamicObjectPString(storage, key, readKey, profile);
11791182
}
11801183

11811184
// this will read from the dynamic object
11821185
@Specialization
11831186
static Object doDynamicObjectString(DynamicObjectStorage storage, String key,
1184-
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1187+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey,
1188+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile profile) {
11851189
Object result = readKey.execute(storage.getStore(), key);
1186-
return result == PNone.NO_VALUE ? null : result;
1190+
return profile.profile(result == PNone.NO_VALUE) ? null : result;
11871191
}
11881192

11891193
@Specialization
11901194
static Object doDynamicObjectPString(DynamicObjectStorage storage, PString key,
1191-
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1195+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey,
1196+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile profile) {
11921197
Object result = readKey.execute(storage.getStore(), key);
1193-
return result == PNone.NO_VALUE ? null : result;
1198+
return profile.profile(result == PNone.NO_VALUE) ? null : result;
11941199
}
11951200

11961201
// this must read from the non-dynamic object storage

0 commit comments

Comments
 (0)