|
25 | 25 | */
|
26 | 26 | package com.oracle.graal.python.builtins.objects.str;
|
27 | 27 |
|
| 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; |
28 | 32 | 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; |
29 | 35 | 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; |
30 | 41 | import com.oracle.graal.python.runtime.sequence.PImmutableSequence;
|
31 | 42 | import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
|
32 | 43 | 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; |
33 | 48 | import com.oracle.truffle.api.interop.InteropLibrary;
|
| 49 | +import com.oracle.truffle.api.library.CachedLibrary; |
34 | 50 | import com.oracle.truffle.api.library.ExportLibrary;
|
35 | 51 | import com.oracle.truffle.api.library.ExportMessage;
|
| 52 | +import com.oracle.truffle.api.profiles.ConditionProfile; |
36 | 53 |
|
37 | 54 | @ExportLibrary(InteropLibrary.class)
|
38 | 55 | public final class PString extends PImmutableSequence {
|
@@ -65,8 +82,91 @@ void setCharSequence(String materialized) {
|
65 | 82 | this.value = materialized;
|
66 | 83 | }
|
67 | 84 |
|
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 | + } |
70 | 170 | }
|
71 | 171 |
|
72 | 172 | @Override
|
@@ -113,6 +213,7 @@ public boolean isHashable() {
|
113 | 213 | return true;
|
114 | 214 | }
|
115 | 215 |
|
| 216 | + @ExportMessage.Ignore |
116 | 217 | @TruffleBoundary(allowInlining = true)
|
117 | 218 | public static int length(String s) {
|
118 | 219 | return s.length();
|
|
0 commit comments