|
6 | 6 | #include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_RepeatBuffer() |
7 | 7 | #include "pycore_call.h" // _PyObject_CallNoArgs() |
8 | 8 | #include "pycore_ceval.h" // _PyEval_GetBuiltin() |
| 9 | +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST() |
9 | 10 | #include "pycore_format.h" // F_LJUST |
10 | 11 | #include "pycore_freelist.h" // _Py_FREELIST_FREE() |
11 | 12 | #include "pycore_global_objects.h"// _Py_GET_GLOBAL_OBJECT() |
@@ -2985,82 +2986,39 @@ _PyBytes_FromBuffer(PyObject *x) |
2985 | 2986 | return NULL; |
2986 | 2987 | } |
2987 | 2988 |
|
2988 | | -static PyObject* |
2989 | | -_PyBytes_FromList(PyObject *x) |
| 2989 | +/* Fast path for a list or tuple of ints. |
| 2990 | + Return 1 on success (*result set to the new bytes object), |
| 2991 | + 0 to fall back to the slow path, or -1 on error (with an exception set). */ |
| 2992 | +static int |
| 2993 | +_PyBytes_FromSequence_lock_held(PyObject *x, PyObject **result) |
2990 | 2994 | { |
2991 | | - Py_ssize_t size = PyList_GET_SIZE(x); |
| 2995 | + *result = NULL; |
| 2996 | + Py_ssize_t size = PySequence_Fast_GET_SIZE(x); |
2992 | 2997 | PyBytesWriter *writer = PyBytesWriter_Create(size); |
2993 | 2998 | if (writer == NULL) { |
2994 | | - return NULL; |
| 2999 | + return -1; |
2995 | 3000 | } |
2996 | | - size = _PyBytesWriter_ResizeToAllocated(writer); |
2997 | 3001 | char *str = PyBytesWriter_GetData(writer); |
2998 | 3002 |
|
2999 | | - for (Py_ssize_t i = 0; i < PyList_GET_SIZE(x); i++) { |
3000 | | - PyObject *item = _PyList_GetItemRef((PyListObject *)x, i); |
3001 | | - if (item == NULL) { |
3002 | | - goto error; |
| 3003 | + PyObject *const *items = PySequence_Fast_ITEMS(x); |
| 3004 | + for (Py_ssize_t i = 0; i < size; i++) { |
| 3005 | + Py_ssize_t value = PyLong_AsSsize_t(items[i]); |
| 3006 | + if (value == -1 && PyErr_Occurred()) { |
| 3007 | + PyBytesWriter_Discard(writer); |
| 3008 | + PyErr_Clear(); |
| 3009 | + return 0; |
3003 | 3010 | } |
3004 | | - Py_ssize_t value = PyNumber_AsSsize_t(item, NULL); |
3005 | | - Py_DECREF(item); |
3006 | | - if (value == -1 && PyErr_Occurred()) |
3007 | | - goto error; |
3008 | 3011 |
|
3009 | 3012 | if (value < 0 || value >= 256) { |
3010 | 3013 | PyErr_SetString(PyExc_ValueError, |
3011 | 3014 | "bytes must be in range(0, 256)"); |
3012 | | - goto error; |
3013 | | - } |
3014 | | - |
3015 | | - if (i >= size) { |
3016 | | - str = _PyBytesWriter_ResizeAndUpdatePointer(writer, size + 1, str); |
3017 | | - if (str == NULL) { |
3018 | | - goto error; |
3019 | | - } |
3020 | | - |
3021 | | - // Set the writer size to its allocated size |
3022 | | - size = _PyBytesWriter_ResizeToAllocated(writer); |
3023 | | - } |
3024 | | - *str++ = (char) value; |
3025 | | - } |
3026 | | - return PyBytesWriter_FinishWithPointer(writer, str); |
3027 | | - |
3028 | | -error: |
3029 | | - PyBytesWriter_Discard(writer); |
3030 | | - return NULL; |
3031 | | -} |
3032 | | - |
3033 | | -static PyObject* |
3034 | | -_PyBytes_FromTuple(PyObject *x) |
3035 | | -{ |
3036 | | - Py_ssize_t i, size = PyTuple_GET_SIZE(x); |
3037 | | - Py_ssize_t value; |
3038 | | - PyObject *item; |
3039 | | - |
3040 | | - PyBytesWriter *writer = PyBytesWriter_Create(size); |
3041 | | - if (writer == NULL) { |
3042 | | - return NULL; |
3043 | | - } |
3044 | | - char *str = PyBytesWriter_GetData(writer); |
3045 | | - |
3046 | | - for (i = 0; i < size; i++) { |
3047 | | - item = PyTuple_GET_ITEM(x, i); |
3048 | | - value = PyNumber_AsSsize_t(item, NULL); |
3049 | | - if (value == -1 && PyErr_Occurred()) |
3050 | | - goto error; |
3051 | | - |
3052 | | - if (value < 0 || value >= 256) { |
3053 | | - PyErr_SetString(PyExc_ValueError, |
3054 | | - "bytes must be in range(0, 256)"); |
3055 | | - goto error; |
| 3015 | + PyBytesWriter_Discard(writer); |
| 3016 | + return -1; |
3056 | 3017 | } |
3057 | 3018 | *str++ = (char) value; |
3058 | 3019 | } |
3059 | | - return PyBytesWriter_Finish(writer); |
3060 | | - |
3061 | | - error: |
3062 | | - PyBytesWriter_Discard(writer); |
3063 | | - return NULL; |
| 3020 | + *result = PyBytesWriter_Finish(writer); |
| 3021 | + return *result != NULL ? 1 : -1; |
3064 | 3022 | } |
3065 | 3023 |
|
3066 | 3024 | static PyObject * |
@@ -3143,11 +3101,15 @@ PyBytes_FromObject(PyObject *x) |
3143 | 3101 | if (PyObject_CheckBuffer(x)) |
3144 | 3102 | return _PyBytes_FromBuffer(x); |
3145 | 3103 |
|
3146 | | - if (PyList_CheckExact(x)) |
3147 | | - return _PyBytes_FromList(x); |
3148 | | - |
3149 | | - if (PyTuple_CheckExact(x)) |
3150 | | - return _PyBytes_FromTuple(x); |
| 3104 | + if (PyList_CheckExact(x) || PyTuple_CheckExact(x)) { |
| 3105 | + int rc; |
| 3106 | + Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST(x); |
| 3107 | + rc = _PyBytes_FromSequence_lock_held(x, &result); |
| 3108 | + Py_END_CRITICAL_SECTION_SEQUENCE_FAST(); |
| 3109 | + if (rc != 0) { |
| 3110 | + return result; |
| 3111 | + } |
| 3112 | + } |
3151 | 3113 |
|
3152 | 3114 | if (!PyUnicode_Check(x)) { |
3153 | 3115 | it = PyObject_GetIter(x); |
|
0 commit comments