Skip to content

Commit d5822e4

Browse files
committed
specialize the length method for PStrings
1 parent 44a114d commit d5822e4

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/NativeCharSequence.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ public String materialize() {
8383
return materialized;
8484
}
8585

86+
public String materialize(PCallCapiFunction node) {
87+
if (!isMaterialized()) {
88+
materialized = (String) node.call(NativeCAPISymbols.FUN_PY_TRUFFLE_CSTR_TO_STRING, ptr);
89+
}
90+
return materialized;
91+
}
92+
8693
Object getPtr() {
8794
return ptr;
8895
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/PString.java

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,31 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.str;
2727

28+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
29+
30+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
31+
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.PCallCapiFunction;
2832
import com.oracle.graal.python.builtins.objects.cext.PythonNativeWrapperLibrary;
33+
import com.oracle.graal.python.builtins.objects.function.PArguments.ThreadState;
34+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
2935
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
36+
import com.oracle.graal.python.nodes.PRaiseNode;
37+
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
38+
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
39+
import com.oracle.graal.python.nodes.call.CallNode;
40+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
3041
import com.oracle.graal.python.runtime.sequence.PImmutableSequence;
3142
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
3243
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
44+
import com.oracle.truffle.api.dsl.Cached;
45+
import com.oracle.truffle.api.dsl.Cached.Exclusive;
46+
import com.oracle.truffle.api.dsl.Cached.Shared;
47+
import com.oracle.truffle.api.dsl.Specialization;
3348
import com.oracle.truffle.api.interop.InteropLibrary;
49+
import com.oracle.truffle.api.library.CachedLibrary;
3450
import com.oracle.truffle.api.library.ExportLibrary;
3551
import com.oracle.truffle.api.library.ExportMessage;
52+
import com.oracle.truffle.api.profiles.ConditionProfile;
3653

3754
@ExportLibrary(InteropLibrary.class)
3855
public final class PString extends PImmutableSequence {
@@ -65,8 +82,91 @@ void setCharSequence(String materialized) {
6582
this.value = materialized;
6683
}
6784

68-
public int len() {
69-
return value.length();
85+
@ExportMessage
86+
static class LengthWithState {
87+
static boolean isString(CharSequence seq) {
88+
return seq instanceof String;
89+
}
90+
91+
static boolean isLazyString(CharSequence seq) {
92+
return seq instanceof LazyString;
93+
}
94+
95+
static boolean isNativeString(CharSequence seq) {
96+
return seq instanceof NativeCharSequence;
97+
}
98+
99+
static boolean isMaterialized(CharSequence seq) {
100+
return ((NativeCharSequence) seq).isMaterialized();
101+
}
102+
103+
static boolean hasBuiltinLen(PString self, LookupInheritedAttributeNode.Dynamic lookupSelf, LookupAttributeInMRONode.Dynamic lookupString) {
104+
return lookupSelf.execute(self, __LEN__) == lookupString.execute(PythonBuiltinClassType.PString, __LEN__);
105+
}
106+
107+
static boolean isBuiltin(PString self, IsBuiltinClassProfile p) {
108+
return p.profileIsAnyBuiltinObject(self);
109+
}
110+
111+
@Specialization(guards = {
112+
"isString(self.getCharSequence())",
113+
"isBuiltin(self, profile) || hasBuiltinLen(self, lookupSelf, lookupString)"
114+
}, limit = "1")
115+
static int string(PString self, @SuppressWarnings("unused") ThreadState state,
116+
@SuppressWarnings("unused") @Shared("builtinProfile") @Cached IsBuiltinClassProfile profile,
117+
@SuppressWarnings("unused") @Shared("lookupSelf") @Cached LookupInheritedAttributeNode.Dynamic lookupSelf,
118+
@SuppressWarnings("unused") @Shared("lookupString") @Cached LookupAttributeInMRONode.Dynamic lookupString) {
119+
return ((String) self.value).length();
120+
}
121+
122+
@Specialization(guards = {
123+
"isLazyString(self.getCharSequence())",
124+
"isBuiltin(self, profile) || hasBuiltinLen(self, lookupSelf, lookupString)"
125+
}, limit = "1")
126+
static int lazyString(PString self, @SuppressWarnings("unused") ThreadState state,
127+
@SuppressWarnings("unused") @Shared("builtinProfile") @Cached IsBuiltinClassProfile profile,
128+
@SuppressWarnings("unused") @Shared("lookupSelf") @Cached LookupInheritedAttributeNode.Dynamic lookupSelf,
129+
@SuppressWarnings("unused") @Shared("lookupString") @Cached LookupAttributeInMRONode.Dynamic lookupString) {
130+
return ((LazyString) self.value).length();
131+
}
132+
133+
@Specialization(guards = {
134+
"isNativeString(self.getCharSequence())", "isMaterialized(self.getCharSequence())",
135+
"isBuiltin(self, profile) || hasBuiltinLen(self, lookupSelf, lookupString)"
136+
}, limit = "1")
137+
static int nativeString(PString self, @SuppressWarnings("unused") ThreadState state,
138+
@SuppressWarnings("unused") @Shared("builtinProfile") @Cached IsBuiltinClassProfile profile,
139+
@SuppressWarnings("unused") @Shared("lookupSelf") @Cached LookupInheritedAttributeNode.Dynamic lookupSelf,
140+
@SuppressWarnings("unused") @Shared("lookupString") @Cached LookupAttributeInMRONode.Dynamic lookupString) {
141+
return ((NativeCharSequence) self.value).length();
142+
}
143+
144+
@Specialization(guards = {
145+
"isNativeString(self.getCharSequence())", "!isMaterialized(self.getCharSequence())",
146+
"isBuiltin(self, profile) || hasBuiltinLen(self, lookupSelf, lookupString)"
147+
}, replaces = "nativeString", limit = "1")
148+
static int nativeStringMat(PString self, @SuppressWarnings("unused") ThreadState state,
149+
@SuppressWarnings("unused") @Shared("builtinProfile") @Cached IsBuiltinClassProfile profile,
150+
@SuppressWarnings("unused") @Shared("lookupSelf") @Cached LookupInheritedAttributeNode.Dynamic lookupSelf,
151+
@SuppressWarnings("unused") @Shared("lookupString") @Cached LookupAttributeInMRONode.Dynamic lookupString,
152+
@Cached PCallCapiFunction callCapi) {
153+
NativeCharSequence ncs = (NativeCharSequence) self.value;
154+
ncs.materialize(callCapi);
155+
return ncs.length();
156+
}
157+
158+
@Specialization(replaces = {"string", "lazyString", "nativeString", "nativeStringMat"})
159+
static int subclassedString(PString self, ThreadState state,
160+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile gotState,
161+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile hasLen,
162+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile ltZero,
163+
@Exclusive @Cached LookupInheritedAttributeNode.Dynamic getLenNode,
164+
@Exclusive @Cached CallNode callNode,
165+
@Exclusive @Cached PRaiseNode raiseNode,
166+
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
167+
// call the generic implementation in the superclass
168+
return self.lengthWithState(state, gotState, hasLen, ltZero, getLenNode, callNode, raiseNode, lib);
169+
}
70170
}
71171

72172
@Override
@@ -113,6 +213,7 @@ public boolean isHashable() {
113213
return true;
114214
}
115215

216+
@ExportMessage.Ignore
116217
@TruffleBoundary(allowInlining = true)
117218
public static int length(String s) {
118219
return s.length();

0 commit comments

Comments
 (0)