Skip to content

Commit ed32f61

Browse files
committed
Support native strings in PyUnicode_AsUnicodeAndSize
1 parent 834120a commit ed32f61

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

graalpython/com.oracle.graal.python.cext/src/unicodeobject.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3759,12 +3759,25 @@ PyUnicode_AsUTF8(PyObject *unicode)
37593759
Py_UNICODE *
37603760
PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size)
37613761
{
3762-
// GraalPy change: different implementation
3763-
Py_UNICODE* charptr = GraalPyTruffle_Unicode_AsUnicodeAndSize_CharPtr(unicode);
3764-
if (charptr && size) {
3765-
*size = GraalPyTruffle_Unicode_AsUnicodeAndSize_Size(unicode);
3762+
if (!PyUnicode_Check(unicode)) {
3763+
PyErr_BadArgument();
3764+
return NULL;
3765+
}
3766+
// GraalPy change: upcall for managed objects
3767+
if (points_to_py_handle_space(unicode)) {
3768+
return GraalPyTruffleUnicode_AsUnicodeAndSize(unicode, size);
3769+
}
3770+
Py_UNICODE *w = _PyUnicode_WSTR(unicode);
3771+
if (w == NULL) {
3772+
// GraalPy change: upcall
3773+
if (GraalPyTruffleUnicode_FillUnicode(unicode) == -1) {
3774+
return NULL;
3775+
}
3776+
w = _PyUnicode_WSTR(unicode);
37663777
}
3767-
return charptr;
3778+
if (size != NULL)
3779+
*size = PyUnicode_WSTR_LENGTH(unicode);
3780+
return w;
37683781
}
37693782

37703783
/* Deprecated APIs */

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_unicode.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,8 @@ class TestPyUnicode(CPyExtTestCase):
738738
lambda: (
739739
("hello", b'\x68\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00',
740740
b"\x68\x00\x00\x00\x65\x00\x00\x00\x6c\x00\x00\x00\x6c\x00\x00\x00\x6f\x00\x00\x00"),
741+
(UnicodeSubclass("hello"), b'\x68\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00',
742+
b"\x68\x00\x00\x00\x65\x00\x00\x00\x6c\x00\x00\x00\x6c\x00\x00\x00\x6f\x00\x00\x00"),
741743
),
742744
code=""" PyObject* wrap_PyUnicode_AsUnicode(PyObject* unicodeObj, PyObject* expected_16, PyObject* expected_32) {
743745
Py_ssize_t n = Py_UNICODE_SIZE == 2 ? PyBytes_Size(expected_16) : PyBytes_Size(expected_32);
@@ -765,6 +767,8 @@ class TestPyUnicode(CPyExtTestCase):
765767
lambda: (
766768
("hello", b'\x68\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00',
767769
b"\x68\x00\x00\x00\x65\x00\x00\x00\x6c\x00\x00\x00\x6c\x00\x00\x00\x6f\x00\x00\x00"),
770+
(UnicodeSubclass("hello"), b'\x68\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00',
771+
b"\x68\x00\x00\x00\x65\x00\x00\x00\x6c\x00\x00\x00\x6c\x00\x00\x00\x6f\x00\x00\x00"),
768772
),
769773
code=""" PyObject* wrap_PyUnicode_AsUnicodeAndSize(PyObject* unicodeObj, PyObject* expected_16, PyObject* expected_32) {
770774
Py_ssize_t n = Py_UNICODE_SIZE == 2 ? PyBytes_Size(expected_16) : PyBytes_Size(expected_32);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextUnicodeBuiltins.java

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,35 +1072,57 @@ static Object doNative(PythonAbstractNativeObject s,
10721072
}
10731073
}
10741074

1075-
@CApiBuiltin(ret = PY_UNICODE_PTR, args = {PyObject}, call = Direct)
1076-
abstract static class PyTruffle_Unicode_AsUnicodeAndSize_CharPtr extends CApiUnaryBuiltinNode {
1075+
@CApiBuiltin(ret = PY_UNICODE_PTR, args = {PyObject, PY_SSIZE_T_PTR}, call = Ignored)
1076+
abstract static class PyTruffleUnicode_AsUnicodeAndSize extends CApiBinaryBuiltinNode {
10771077

10781078
@Specialization
1079-
Object doUnicode(PString s,
1079+
static Object doUnicode(PString s, Object sizePtr,
10801080
@Bind("this") Node inliningTarget,
1081-
@Cached InlinedConditionProfile profile,
1081+
@CachedLibrary(limit = "2") InteropLibrary lib,
1082+
@Cached InlinedConditionProfile hasSizeProfile,
1083+
@Cached InlinedConditionProfile hasUnicodeProfile,
1084+
@Cached CStructAccess.WriteLongNode writeLongNode,
10821085
@Cached UnicodeAsWideCharNode asWideCharNode) {
1083-
if (profile.profile(inliningTarget, s.getWCharBytes() == null)) {
1084-
PBytes bytes = asWideCharNode.executeNativeOrder(inliningTarget, s, CStructs.wchar_t.size());
1086+
int wcharSize = CStructs.wchar_t.size();
1087+
if (hasUnicodeProfile.profile(inliningTarget, s.getWCharBytes() == null)) {
1088+
PBytes bytes = asWideCharNode.executeNativeOrder(inliningTarget, s, wcharSize);
10851089
s.setWCharBytes(bytes);
10861090
}
1091+
if (hasSizeProfile.profile(inliningTarget, !lib.isNull(sizePtr))) {
1092+
writeLongNode.write(sizePtr, s.getWCharBytes().getSequenceStorage().length() / wcharSize);
1093+
}
10871094
return PySequenceArrayWrapper.ensureNativeSequence(s.getWCharBytes());
10881095
}
10891096

10901097
@Fallback
1091-
static Object doError(@SuppressWarnings("unused") Object s,
1098+
@SuppressWarnings("unused")
1099+
static Object doError(Object s, Object sizePtr,
10921100
@Cached PRaiseNode raiseNode) {
10931101
throw raiseNode.raise(TypeError, BAD_ARG_TYPE_FOR_BUILTIN_OP);
10941102
}
10951103
}
10961104

1097-
@CApiBuiltin(ret = Py_ssize_t, args = {PyObject}, call = Direct)
1098-
abstract static class PyTruffle_Unicode_AsUnicodeAndSize_Size extends CApiUnaryBuiltinNode {
1105+
@CApiBuiltin(ret = Int, args = {PyObject}, call = Ignored)
1106+
abstract static class PyTruffleUnicode_FillUnicode extends CApiUnaryBuiltinNode {
10991107

11001108
@Specialization
1101-
static Object doUnicode(PString s) {
1102-
// PyTruffle_Unicode_AsUnicodeAndSize_CharPtr must have been be called before
1103-
return s.getWCharBytes().getSequenceStorage().length() / CStructs.wchar_t.size();
1109+
static Object doNative(PythonAbstractNativeObject s,
1110+
@Bind("this") Node inliningTarget,
1111+
@Cached CastToTruffleStringNode cast,
1112+
@Cached CStructAccess.WriteLongNode writeLongNode,
1113+
@Cached UnicodeAsWideCharNode asWideCharNode,
1114+
@CachedLibrary(limit = "1") PythonBufferAccessLibrary bufferLib,
1115+
@Cached CStructAccess.WritePointerNode writePointerNode,
1116+
@Cached CStructAccess.AllocateNode allocateNode,
1117+
@Cached CStructAccess.WriteByteNode writeByteNode) {
1118+
int wcharSize = CStructs.wchar_t.size();
1119+
PBytes bytes = asWideCharNode.executeNativeOrder(inliningTarget, cast.castKnownString(inliningTarget, s), wcharSize);
1120+
int len = bufferLib.getBufferLength(bytes);
1121+
Object mem = allocateNode.alloc(len + wcharSize, true);
1122+
writeByteNode.writeByteArray(mem, bufferLib.getInternalOrCopiedByteArray(bytes), len, 0, 0);
1123+
writePointerNode.writeToObj(s, CFields.PyASCIIObject__wstr, mem);
1124+
writeLongNode.writeToObject(s, CFields.PyCompactUnicodeObject__wstr_length, len / wcharSize);
1125+
return 0;
11041126
}
11051127
}
11061128

0 commit comments

Comments
 (0)