Skip to content

Commit 5c9d2a2

Browse files
committed
Implement Py_SET_SIZE for managed objects
1 parent 4026838 commit 5c9d2a2

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2640,7 +2640,7 @@ void PyTruffle_SET_TYPE(PyObject *a, PyTypeObject *b) {
26402640
}
26412641
void PyTruffle_SET_SIZE(PyVarObject *a, Py_ssize_t b) {
26422642
if (points_to_py_handle_space(a)) {
2643-
printf("changing the size of an object is not supported\n");
2643+
Graal_PyTruffle_SET_SIZE(a, b);
26442644
} else {
26452645
a->ob_size = b;
26462646
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,27 @@ class TestPyBytes(CPyExtTestCase):
517517
cmpfunc=unhandled_error_compare
518518
)
519519

520+
test_set_size = CPyExtFunction(
521+
lambda args: b'1234',
522+
lambda: ((),),
523+
code="""
524+
PyObject* set_size() {
525+
PyObject* output = PyBytes_FromStringAndSize(NULL, 50);
526+
if (output == NULL)
527+
return NULL;
528+
char* s = PyBytes_AsString(output);
529+
memcpy(s, "1234", 4);
530+
Py_SET_SIZE(output, 4);
531+
return output;
532+
}
533+
""",
534+
resultspec="O",
535+
argspec="",
536+
arguments=[],
537+
callfunction="set_size",
538+
cmpfunc=unhandled_error_compare
539+
)
540+
520541

521542
class ObjectTests(unittest.TestCase):
522543
def test_create_from_buffer(self):

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer;
5151
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectWrapper;
5252
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyThreadState;
53+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyVarObject;
5354
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_hash_t;
5455
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t;
5556
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.VA_LIST_PTR;
@@ -94,6 +95,7 @@
9495
import com.oracle.graal.python.builtins.objects.cext.common.GetNextVaArgNode;
9596
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
9697
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
98+
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
9799
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
98100
import com.oracle.graal.python.builtins.objects.dict.PDict;
99101
import com.oracle.graal.python.builtins.objects.function.PKeyword;
@@ -132,6 +134,10 @@
132134
import com.oracle.graal.python.runtime.PythonOptions;
133135
import com.oracle.graal.python.runtime.exception.PException;
134136
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
137+
import com.oracle.graal.python.runtime.sequence.PSequence;
138+
import com.oracle.graal.python.runtime.sequence.storage.BasicSequenceStorage;
139+
import com.oracle.graal.python.runtime.sequence.storage.EmptySequenceStorage;
140+
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
135141
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
136142
import com.oracle.graal.python.util.PythonUtils;
137143
import com.oracle.truffle.api.CompilerDirectives;
@@ -567,6 +573,29 @@ static PNone doNativeNone() {
567573
}
568574
}
569575

576+
@CApiBuiltin(ret = Void, args = {PyVarObject, Py_ssize_t}, call = Ignored)
577+
abstract static class _PyTruffle_SET_SIZE extends CApiBinaryBuiltinNode {
578+
@Specialization
579+
static PNone set(PSequence obj, long size,
580+
@Bind("this") Node inliningTarget,
581+
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode) {
582+
SequenceStorage storage = getSequenceStorageNode.execute(inliningTarget, obj);
583+
// Can't use SetLenNode as that decrefs items for native storages when shrinking
584+
if (storage instanceof BasicSequenceStorage basicStorage) {
585+
basicStorage.setNewLength((int) size);
586+
} else if (storage instanceof NativeSequenceStorage nativeStorage) {
587+
nativeStorage.setNewLength((int) size);
588+
} else if (storage instanceof EmptySequenceStorage) {
589+
if (size > 0) {
590+
throw CompilerDirectives.shouldNotReachHere("invalid Py_SET_SIZE call");
591+
}
592+
} else {
593+
throw CompilerDirectives.shouldNotReachHere("unhandled storage type");
594+
}
595+
return PNone.NO_VALUE;
596+
}
597+
}
598+
570599
@CApiBuiltin(ret = Void, args = {PyObjectWrapper}, call = Direct)
571600
abstract static class _PyObject_Dump extends CApiUnaryBuiltinNode {
572601

0 commit comments

Comments
 (0)