Skip to content

Commit 972acb8

Browse files
committed
fast path for list sorting with bool/byte/int/long/double/String elements
1 parent e967411 commit 972acb8

File tree

2 files changed

+105
-4
lines changed
  • graalpython

2 files changed

+105
-4
lines changed

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

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
5252

5353
import java.math.BigInteger;
54+
import java.util.Arrays;
55+
import java.util.Comparator;
5456
import java.util.List;
5557

5658
import com.oracle.graal.python.PythonLanguage;
@@ -81,6 +83,7 @@
8183
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
8284
import com.oracle.graal.python.builtins.objects.range.PIntRange;
8385
import com.oracle.graal.python.builtins.objects.str.PString;
86+
import com.oracle.graal.python.builtins.objects.str.StringUtils;
8487
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
8588
import com.oracle.graal.python.nodes.ErrorMessages;
8689
import com.oracle.graal.python.nodes.PGuards;
@@ -105,10 +108,13 @@
105108
import com.oracle.graal.python.runtime.exception.PException;
106109
import com.oracle.graal.python.runtime.exception.PythonErrorType;
107110
import com.oracle.graal.python.runtime.sequence.PSequence;
111+
import com.oracle.graal.python.runtime.sequence.storage.BoolSequenceStorage;
112+
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
108113
import com.oracle.graal.python.runtime.sequence.storage.DoubleSequenceStorage;
109114
import com.oracle.graal.python.runtime.sequence.storage.EmptySequenceStorage;
110115
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
111116
import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage;
117+
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
112118
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
113119
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorageFactory;
114120
import com.oracle.graal.python.util.PythonUtils;
@@ -124,6 +130,7 @@
124130
import com.oracle.truffle.api.dsl.TypeSystemReference;
125131
import com.oracle.truffle.api.frame.VirtualFrame;
126132
import com.oracle.truffle.api.library.CachedLibrary;
133+
import com.oracle.truffle.api.nodes.Node;
127134
import com.oracle.truffle.api.nodes.UnexpectedResultException;
128135
import com.oracle.truffle.api.profiles.ConditionProfile;
129136

@@ -861,6 +868,92 @@ public static ListReverseNode create() {
861868
}
862869
}
863870

871+
abstract static class SimpleSortNode extends Node {
872+
873+
protected static final String SORT = "_sort";
874+
875+
protected abstract void execute(VirtualFrame frame, PList list, SequenceStorage storage);
876+
877+
@Specialization
878+
@TruffleBoundary
879+
void sort(@SuppressWarnings("unused") PList list, BoolSequenceStorage storage) {
880+
int length = storage.length();
881+
int trueValues = 0;
882+
boolean[] array = storage.getInternalBoolArray();
883+
for (int i = 0; i < length; i++) {
884+
if (array[i]) {
885+
trueValues++;
886+
}
887+
}
888+
Arrays.fill(array, 0, length - trueValues, false);
889+
Arrays.fill(array, length - trueValues, length, true);
890+
}
891+
892+
@Specialization
893+
@TruffleBoundary
894+
void sort(@SuppressWarnings("unused") PList list, ByteSequenceStorage storage) {
895+
Arrays.sort(storage.getInternalByteArray(), 0, storage.length());
896+
}
897+
898+
@Specialization
899+
@TruffleBoundary
900+
void sort(@SuppressWarnings("unused") PList list, IntSequenceStorage storage) {
901+
Arrays.sort(storage.getInternalIntArray(), 0, storage.length());
902+
}
903+
904+
@Specialization
905+
@TruffleBoundary
906+
void sort(@SuppressWarnings("unused") PList list, LongSequenceStorage storage) {
907+
Arrays.sort(storage.getInternalLongArray(), 0, storage.length());
908+
}
909+
910+
@Specialization
911+
@TruffleBoundary
912+
void sort(@SuppressWarnings("unused") PList list, DoubleSequenceStorage storage) {
913+
Arrays.sort(storage.getInternalDoubleArray(), 0, storage.length());
914+
}
915+
916+
private static final class StringComparator implements Comparator<Object> {
917+
public int compare(Object o1, Object o2) {
918+
return StringUtils.compareToUnicodeAware((String) o1, (String) o2);
919+
}
920+
}
921+
922+
private static final StringComparator COMPARATOR = new StringComparator();
923+
924+
@Specialization(guards = "isStringOnly(storage)")
925+
@TruffleBoundary
926+
void sort(@SuppressWarnings("unused") PList list, ObjectSequenceStorage storage) {
927+
Arrays.sort(storage.getInternalArray(), 0, storage.length(), COMPARATOR);
928+
}
929+
930+
@TruffleBoundary
931+
protected static boolean isStringOnly(ObjectSequenceStorage storage) {
932+
int length = storage.length();
933+
Object[] array = storage.getInternalArray();
934+
for (int i = 0; i < length; i++) {
935+
Object value = array[i];
936+
if (!(value instanceof String)) {
937+
return false;
938+
}
939+
}
940+
return true;
941+
}
942+
943+
protected static boolean isSimpleType(SequenceStorage storage) {
944+
return storage instanceof BoolSequenceStorage || storage instanceof ByteSequenceStorage || storage instanceof IntSequenceStorage || storage instanceof LongSequenceStorage ||
945+
storage instanceof DoubleSequenceStorage || (storage instanceof ObjectSequenceStorage && isStringOnly((ObjectSequenceStorage) storage));
946+
}
947+
948+
@Specialization(guards = "!isSimpleType(storage)")
949+
void defaultSort(VirtualFrame frame, PList list, @SuppressWarnings("unused") SequenceStorage storage,
950+
@Cached("create(SORT)") GetAttributeNode sort,
951+
@Cached CallNode callSort) {
952+
Object sortMethod = sort.executeObject(frame, list);
953+
callSort.execute(frame, sortMethod, PythonUtils.EMPTY_OBJECT_ARRAY, PKeyword.EMPTY_KEYWORDS);
954+
}
955+
}
956+
864957
// list.sort(key=, reverse=)
865958
@Builtin(name = SORT, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, needsFrame = true)
866959
@GenerateNodeFactory
@@ -878,10 +971,10 @@ protected static boolean maySideEffect(PList list, PKeyword[] keywords) {
878971
return true;
879972
}
880973
if (keywords.length > 0) {
881-
if (keywords[0].getName().equals(KEY)) {
974+
if (KEY.equals(keywords[0].getName())) {
882975
return true;
883976
}
884-
if (keywords.length > 1 && keywords[1].getName().equals(KEY)) {
977+
if (keywords.length > 1 && KEY.equals(keywords[1].getName())) {
885978
return true;
886979
}
887980
}
@@ -901,6 +994,14 @@ Object none(VirtualFrame frame, PList list, Object[] arguments, PKeyword[] keywo
901994
return PNone.NONE;
902995
}
903996

997+
@Specialization(guards = {"isSortable(list, lenNode)", "arguments.length == 0", "keywords.length == 0", "!maySideEffect(list, keywords)"})
998+
Object simple(VirtualFrame frame, PList list, @SuppressWarnings("unused") Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
999+
@Cached SimpleSortNode simpleSort,
1000+
@SuppressWarnings("unused") @Cached SequenceStorageNodes.LenNode lenNode) {
1001+
simpleSort.execute(frame, list, list.getSequenceStorage());
1002+
return PNone.NONE;
1003+
}
1004+
9041005
@Specialization(guards = {"isSortable(list, lenNode)", "maySideEffect(list, keywords)"})
9051006
Object withKey(VirtualFrame frame, PList list, Object[] arguments, PKeyword[] keywords,
9061007
@Cached("create(SORT)") GetAttributeNode sort,

graalpython/lib-graalpython/type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __dir__(klass):
5353
# we merge classes is unimportant
5454
for base in bases:
5555
names.update(_classdir(base))
56-
return sorted(list(names))
56+
return sorted(names)
5757
_classdir = __dir__
5858

5959

@@ -70,7 +70,7 @@ def __dir__(obj):
7070
klass = getattr(obj, '__class__', None)
7171
if klass is not None:
7272
names.update(_classdir(klass))
73-
return sorted(list(names))
73+
return sorted(names)
7474
_objectdir = __dir__
7575

7676

0 commit comments

Comments
 (0)