|
53 | 53 | import java.nio.charset.CharsetEncoder;
|
54 | 54 | import java.nio.charset.StandardCharsets;
|
55 | 55 |
|
| 56 | +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.SizeofWCharNode; |
56 | 57 | import com.oracle.graal.python.builtins.objects.cext.DynamicObjectNativeWrapper.PAsPointerNode;
|
57 | 58 | import com.oracle.graal.python.builtins.objects.cext.DynamicObjectNativeWrapper.ToPyObjectNode;
|
58 | 59 | import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode;
|
| 60 | +import com.oracle.graal.python.builtins.objects.str.NativeCharSequence; |
59 | 61 | import com.oracle.graal.python.builtins.objects.str.PString;
|
60 | 62 | import com.oracle.graal.python.builtins.objects.str.StringNodes.StringLenNode;
|
| 63 | +import com.oracle.graal.python.builtins.objects.str.StringNodes.StringMaterializeNode; |
| 64 | +import com.oracle.truffle.api.CompilerDirectives; |
61 | 65 | import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
62 | 66 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
63 | 67 | import com.oracle.truffle.api.dsl.Cached;
|
|
67 | 71 | import com.oracle.truffle.api.library.CachedLibrary;
|
68 | 72 | import com.oracle.truffle.api.library.ExportLibrary;
|
69 | 73 | import com.oracle.truffle.api.library.ExportMessage;
|
| 74 | +import com.oracle.truffle.api.profiles.ConditionProfile; |
70 | 75 | import com.oracle.truffle.llvm.spi.NativeTypeLibrary;
|
71 | 76 |
|
72 | 77 | public abstract class PyUnicodeWrappers {
|
@@ -163,6 +168,12 @@ Object readMember(String member,
|
163 | 168 | if (isMemberReadable(member)) {
|
164 | 169 | int elementSize = (int) sizeofWcharNode.execute();
|
165 | 170 | PString s = getPString(lib);
|
| 171 | + CharSequence content = s.getCharSequence(); |
| 172 | + |
| 173 | + if (content instanceof NativeCharSequence) { |
| 174 | + // in this case, we can just return the pointer |
| 175 | + return ((NativeCharSequence) content).getPtr(); |
| 176 | + } |
166 | 177 | return new PySequenceArrayWrapper(asWideCharNode.execute(s, elementSize, stringLenNode.execute(s)), elementSize);
|
167 | 178 | }
|
168 | 179 | throw UnknownIdentifierException.create(member);
|
@@ -209,25 +220,46 @@ boolean isMemberReadable(String member) {
|
209 | 220 | @ExportMessage
|
210 | 221 | Object readMember(String member,
|
211 | 222 | @CachedLibrary("this") PythonNativeWrapperLibrary lib,
|
| 223 | + @Cached ConditionProfile storageProfile, |
| 224 | + @Cached StringMaterializeNode materializeNode, |
212 | 225 | @Cached CExtNodes.SizeofWCharNode sizeofWcharNode) throws UnknownIdentifierException {
|
213 | 226 | // padding(24), ready(1), ascii(1), compact(1), kind(3), interned(2)
|
214 | 227 | int value = 0b000000000000000000000000_1_0_0_000_00;
|
215 |
| - if (onlyAscii(getPString(lib).getValue())) { |
| 228 | + PString delegate = getPString(lib); |
| 229 | + if (onlyAscii(delegate, storageProfile, materializeNode)) { |
216 | 230 | value |= 0b1_0_000_00;
|
217 | 231 | }
|
218 |
| - value |= ((int) sizeofWcharNode.execute() << 2) & 0b11100; |
| 232 | + value |= (getKind(delegate, storageProfile, sizeofWcharNode) << 2) & 0b11100; |
219 | 233 | if (isMemberReadable(member)) {
|
220 | 234 | // it's a bit field; so we need to return the whole 32-bit word
|
221 | 235 | return value;
|
222 | 236 | }
|
223 | 237 | throw UnknownIdentifierException.create(member);
|
224 | 238 | }
|
225 | 239 |
|
226 |
| - private boolean onlyAscii(String value) { |
| 240 | + private boolean onlyAscii(PString value, ConditionProfile storageProfile, StringMaterializeNode stringMaterializeNode) { |
| 241 | + CharSequence storage = value.getCharSequence(); |
| 242 | + |
| 243 | + // important: avoid materialization of native sequences |
| 244 | + if (storageProfile.profile(storage instanceof NativeCharSequence)) { |
| 245 | + return ((NativeCharSequence) storage).isAsciiOnly(); |
| 246 | + } |
| 247 | + |
227 | 248 | if (asciiEncoder == null) {
|
| 249 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
228 | 250 | asciiEncoder = newAsciiEncoder();
|
229 | 251 | }
|
230 |
| - return doCheck(value, asciiEncoder); |
| 252 | + return doCheck(stringMaterializeNode.execute(value), asciiEncoder); |
| 253 | + } |
| 254 | + |
| 255 | + private int getKind(PString value, ConditionProfile storageProfile, SizeofWCharNode sizeofWcharNode) { |
| 256 | + CharSequence storage = value.getCharSequence(); |
| 257 | + |
| 258 | + // important: avoid materialization of native sequences |
| 259 | + if (storageProfile.profile(storage instanceof NativeCharSequence)) { |
| 260 | + return ((NativeCharSequence) storage).getElementSize(); |
| 261 | + } |
| 262 | + return (int) sizeofWcharNode.execute(); |
231 | 263 | }
|
232 | 264 |
|
233 | 265 | @TruffleBoundary
|
|
0 commit comments