Skip to content

Commit 30ce3d4

Browse files
authored
gh-158585: Simplify PyBytesWriter_Finish() (#158822)
PyBytesWriter_Finish() doesn't need to check the size. It's known to be valid. PyBytesWriter_Create() now only calls byteswriter_resize() if the size is larger than the small buffer. Remove byteswriter_data() function: call static inline _PyBytesWriter_GetData() function directly.
1 parent d95b7ae commit 30ce3d4

4 files changed

Lines changed: 57 additions & 56 deletions

File tree

‎Modules/_struct.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2498,7 +2498,8 @@ Struct_pack_impl(PyStructObject *self, PyObject * const *values,
24982498
return NULL;
24992499
}
25002500

2501-
return PyBytesWriter_FinishWithSize(writer, self->s_size);
2501+
assert(PyBytesWriter_GetSize(writer) == self->s_size);
2502+
return PyBytesWriter_Finish(writer);
25022503
}
25032504

25042505
/*[clinic input]

‎Objects/bytesobject.c‎

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,12 +3731,6 @@ _PyBytes_RepeatBuffer(char* dest, Py_ssize_t len_dest,
37313731
// one extra NUL byte which is a common error.
37323732
#define PyBytesWriter_CANARY_BYTE PYMEM_DEADBYTE
37333733

3734-
static inline char*
3735-
byteswriter_data(PyBytesWriter *writer)
3736-
{
3737-
return _PyBytesWriter_GetData(writer);
3738-
}
3739-
37403734

37413735
static inline Py_ssize_t
37423736
byteswriter_allocated(PyBytesWriter *writer)
@@ -3758,7 +3752,7 @@ byteswriter_allocated(PyBytesWriter *writer)
37583752
static void
37593753
byteswriter_write_canary_byte(PyBytesWriter *writer)
37603754
{
3761-
unsigned char *data = (unsigned char*)byteswriter_data(writer);
3755+
unsigned char *data = (unsigned char*)_PyBytesWriter_GetData(writer);
37623756
data[writer->size] = PyBytesWriter_CANARY_BYTE;
37633757
}
37643758

@@ -3770,7 +3764,7 @@ byteswriter_reset_trailing_byte(PyBytesWriter *writer)
37703764
// bytes/bytearray expects the last byte to be a null byte.
37713765
// Reset the last byte to null for bytes/bytearray.
37723766
Py_ssize_t allocated = byteswriter_allocated(writer);
3773-
char *data = byteswriter_data(writer);
3767+
char *data = _PyBytesWriter_GetData(writer);
37743768
data[allocated] = '\0';
37753769
}
37763770
#endif
@@ -3801,7 +3795,7 @@ byteswriter_check_consistency(PyBytesWriter *writer)
38013795
}
38023796

38033797
#ifdef Py_DEBUG
3804-
const unsigned char *data = (const unsigned char*)byteswriter_data(writer);
3798+
const unsigned char *data = (const unsigned char*)_PyBytesWriter_GetData(writer);
38053799
unsigned char canary = data[writer->size];
38063800
if (canary != PyBytesWriter_CANARY_BYTE) {
38073801
_Py_FatalErrorFormat(__func__,
@@ -3895,7 +3889,7 @@ byteswriter_resize(PyBytesWriter *writer, Py_ssize_t new_size, int resize)
38953889
if (resize) {
38963890
Py_ssize_t old_size = writer->size;
38973891
assert(allocated > old_size);
3898-
memset(byteswriter_data(writer) + old_size, PyBytesWrite_NEW_BYTE,
3892+
memset(_PyBytesWriter_GetData(writer) + old_size, PyBytesWrite_NEW_BYTE,
38993893
allocated - old_size);
39003894
}
39013895
#endif
@@ -3921,24 +3915,25 @@ byteswriter_create(Py_ssize_t size, int use_bytearray)
39213915
}
39223916
}
39233917
writer->obj = NULL;
3924-
writer->size = 0;
3918+
writer->size = size;
39253919
writer->use_bytearray = use_bytearray;
39263920
writer->overallocate = !use_bytearray;
39273921

3928-
if (size >= 1) {
3922+
Py_ssize_t allocated = sizeof(writer->small_buffer) - 1;
3923+
if (size > allocated) {
39293924
if (byteswriter_resize(writer, size, 0) < 0) {
39303925
#ifdef Py_DEBUG
39313926
// Write the canary byte so byteswriter_check_consistency()
39323927
// doesn't fail in PyBytesWriter_Discard()
3928+
writer->size = 0;
39333929
byteswriter_write_canary_byte(writer);
39343930
#endif
39353931
PyBytesWriter_Discard(writer);
39363932
return NULL;
39373933
}
3938-
writer->size = size;
39393934
}
39403935
#ifdef Py_DEBUG
3941-
memset(byteswriter_data(writer), PyBytesWrite_NEW_BYTE,
3936+
memset(_PyBytesWriter_GetData(writer), PyBytesWrite_NEW_BYTE,
39423937
byteswriter_allocated(writer));
39433938
byteswriter_write_canary_byte(writer);
39443939
#endif
@@ -3967,34 +3962,23 @@ PyBytesWriter_Discard(PyBytesWriter *writer)
39673962
}
39683963

39693964
assert(byteswriter_check_consistency(writer));
3970-
#ifdef Py_DEBUG
39713965
if (writer->obj != NULL) {
3966+
#ifdef Py_DEBUG
39723967
byteswriter_reset_trailing_byte(writer);
3973-
}
39743968
#endif
3975-
3976-
Py_XDECREF(writer->obj);
3969+
Py_DECREF(writer->obj);
3970+
}
39773971
_Py_FREELIST_FREE(bytes_writers, writer, PyMem_Free);
39783972
}
39793973

39803974

3981-
PyObject*
3982-
PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
3975+
static inline PyObject*
3976+
byteswriter_finish_with_size(PyBytesWriter *writer, Py_ssize_t final_size)
39833977
{
39843978
assert(byteswriter_check_consistency(writer));
39853979

3986-
if (size < 0) {
3987-
PyErr_Format(PyExc_ValueError, "size must be positive");
3988-
goto error;
3989-
}
3990-
3991-
if (size > writer->size) {
3992-
PyErr_SetString(PyExc_ValueError, "size larger than allocated size");
3993-
goto error;
3994-
}
3995-
39963980
PyObject *result;
3997-
if (size == 0 && !writer->use_bytearray) {
3981+
if (final_size == 0 && !writer->use_bytearray) {
39983982
result = bytes_get_empty();
39993983
if (writer->obj != NULL) {
40003984
#ifdef Py_DEBUG
@@ -4011,19 +3995,19 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
40113995
#endif
40123996

40133997
if (writer->use_bytearray) {
4014-
if (size != PyByteArray_GET_SIZE(writer->obj)) {
4015-
if (PyByteArray_Resize(writer->obj, size)) {
3998+
if (final_size != PyByteArray_GET_SIZE(writer->obj)) {
3999+
if (PyByteArray_Resize(writer->obj, final_size)) {
40164000
goto error;
40174001
}
40184002
}
40194003
}
40204004
else {
4021-
if (size == 1) {
4005+
if (final_size == 1) {
40224006
unsigned char ch = PyBytes_AS_STRING(writer->obj)[0];
40234007
Py_SETREF(writer->obj, bytes_get_char(ch));
40244008
}
4025-
else if (size != PyBytes_GET_SIZE(writer->obj)) {
4026-
if (bytes_resize_inplace(&writer->obj, size)) {
4009+
else if (final_size != PyBytes_GET_SIZE(writer->obj)) {
4010+
if (bytes_resize_inplace(&writer->obj, final_size)) {
40274011
goto error;
40284012
}
40294013
}
@@ -4036,18 +4020,18 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
40364020
// Create an object from the small buffer
40374021
const char *buffer = (const char *)writer->small_buffer;
40384022
if (writer->use_bytearray) {
4039-
result = PyByteArray_FromStringAndSize(buffer, size);
4023+
result = PyByteArray_FromStringAndSize(buffer, final_size);
40404024
}
40414025
else {
4042-
if (size == 1) {
4026+
if (final_size == 1) {
40434027
result = bytes_get_char((uint8_t)buffer[0]);
40444028
}
40454029
else {
4046-
result = bytes_alloc(size);
4030+
result = bytes_alloc(final_size);
40474031
if (result == NULL) {
40484032
goto error;
40494033
}
4050-
memcpy(PyBytes_AS_STRING(result), buffer, size);
4034+
memcpy(PyBytes_AS_STRING(result), buffer, final_size);
40514035
}
40524036
}
40534037
}
@@ -4061,17 +4045,36 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
40614045
return NULL;
40624046
}
40634047

4048+
PyObject*
4049+
PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
4050+
{
4051+
if (size < 0) {
4052+
PyErr_Format(PyExc_ValueError, "size must be positive");
4053+
goto error;
4054+
}
4055+
if (size > writer->size) {
4056+
PyErr_SetString(PyExc_ValueError, "size larger than allocated size");
4057+
goto error;
4058+
}
4059+
return byteswriter_finish_with_size(writer, size);
4060+
4061+
error:
4062+
PyBytesWriter_Discard(writer);
4063+
return NULL;
4064+
}
4065+
40644066
PyObject*
40654067
PyBytesWriter_Finish(PyBytesWriter *writer)
40664068
{
4067-
return PyBytesWriter_FinishWithSize(writer, writer->size);
4069+
return byteswriter_finish_with_size(writer, writer->size);
40684070
}
40694071

40704072

40714073
PyObject*
40724074
PyBytesWriter_FinishWithPointer(PyBytesWriter *writer, void *buf)
40734075
{
4074-
Py_ssize_t size = (char*)buf - byteswriter_data(writer);
4076+
Py_ssize_t size = (char*)buf - _PyBytesWriter_GetData(writer);
4077+
// Call PyBytesWriter_FinishWithSize() to check size
40754078
return PyBytesWriter_FinishWithSize(writer, size);
40764079
}
40774080

@@ -4081,7 +4084,7 @@ PyBytesWriter_GetData(PyBytesWriter *writer)
40814084
{
40824085
assert(byteswriter_check_consistency(writer));
40834086

4084-
return byteswriter_data(writer);
4087+
return _PyBytesWriter_GetData(writer);
40854088
}
40864089

40874090

@@ -4125,11 +4128,11 @@ static void*
41254128
_PyBytesWriter_ResizeAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size,
41264129
void *data)
41274130
{
4128-
Py_ssize_t pos = (char*)data - byteswriter_data(writer);
4131+
Py_ssize_t pos = (char*)data - _PyBytesWriter_GetData(writer);
41294132
if (PyBytesWriter_Resize(writer, size) < 0) {
41304133
return NULL;
41314134
}
4132-
return byteswriter_data(writer) + pos;
4135+
return _PyBytesWriter_GetData(writer) + pos;
41334136
}
41344137

41354138

@@ -4176,11 +4179,11 @@ void*
41764179
PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size,
41774180
void *buf)
41784181
{
4179-
Py_ssize_t pos = (char*)buf - byteswriter_data(writer);
4182+
Py_ssize_t pos = (char*)buf - _PyBytesWriter_GetData(writer);
41804183
if (PyBytesWriter_Grow(writer, size) < 0) {
41814184
return NULL;
41824185
}
4183-
return byteswriter_data(writer) + pos;
4186+
return _PyBytesWriter_GetData(writer) + pos;
41844187
}
41854188

41864189

@@ -4201,7 +4204,7 @@ PyBytesWriter_WriteBytes(PyBytesWriter *writer,
42014204
if (PyBytesWriter_Grow(writer, size) < 0) {
42024205
return -1;
42034206
}
4204-
char *buf = byteswriter_data(writer);
4207+
char *buf = _PyBytesWriter_GetData(writer);
42054208
memcpy(buf + pos, bytes, size);
42064209

42074210
assert(byteswriter_check_consistency(writer));
@@ -4232,7 +4235,7 @@ PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)
42324235
return -1;
42334236
}
42344237

4235-
Py_ssize_t size = buf - byteswriter_data(writer);
4238+
Py_ssize_t size = buf - _PyBytesWriter_GetData(writer);
42364239
return PyBytesWriter_Resize(writer, size);
42374240
}
42384241

‎Objects/unicodeobject.c‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4880,7 +4880,7 @@ _PyUnicode_EncodeUTF7(PyObject *str,
48804880
else { /* not in a shift sequence */
48814881
if (ch == '+') {
48824882
*out++ = '+';
4883-
*out++ = '-';
4883+
*out++ = '-';
48844884
}
48854885
else if (ENCODE_DIRECT(ch)) {
48864886
*out++ = (char) ch;
@@ -8644,10 +8644,7 @@ _PyUnicode_EncodeIconv(const char *encoding, PyObject *unicode,
86448644
iconv(cd, NULL, NULL, NULL, NULL);
86458645
}
86468646

8647-
if (PyBytesWriter_Resize(writer, out - (char *)PyBytesWriter_GetData(writer)) < 0) {
8648-
goto done;
8649-
}
8650-
result = PyBytesWriter_Finish(writer);
8647+
result = PyBytesWriter_FinishWithPointer(writer, out);
86518648
writer = NULL;
86528649

86538650
done:

‎Python/assemble.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ assemble_free(struct assembler *a)
102102

103103
static inline void
104104
write_except_byte(struct assembler *a, int byte) {
105-
unsigned char *p = (unsigned char *) PyBytesWriter_GetData(a->a_except_table_writer);
105+
unsigned char *p = PyBytesWriter_GetData(a->a_except_table_writer);
106106
p[a->a_except_table_off++] = byte;
107107
}
108108

0 commit comments

Comments
 (0)