mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
bpo-40521: Make bytes singletons per interpreter (GH-21074)
Each interpreter now has its own empty bytes string and single byte character singletons. Replace STRINGLIB_EMPTY macro with STRINGLIB_GET_EMPTY() macro.
This commit is contained in:
parent
32f2eda859
commit
c41eed1a87
13 changed files with 96 additions and 53 deletions
|
@ -18,9 +18,6 @@ class bytes "PyBytesObject *" "&PyBytes_Type"
|
|||
|
||||
#include "clinic/bytesobject.c.h"
|
||||
|
||||
static PyBytesObject *characters[UCHAR_MAX + 1];
|
||||
static PyBytesObject *nullstring;
|
||||
|
||||
_Py_IDENTIFIER(__bytes__);
|
||||
|
||||
/* PyBytesObject_SIZE gives the basic size of a string; any memory allocation
|
||||
|
@ -35,6 +32,15 @@ _Py_IDENTIFIER(__bytes__);
|
|||
Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer,
|
||||
char *str);
|
||||
|
||||
|
||||
static struct _Py_bytes_state*
|
||||
get_bytes_state(void)
|
||||
{
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
return &interp->bytes;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
For PyBytes_FromString(), the parameter `str' points to a null-terminated
|
||||
string containing exactly `size' bytes.
|
||||
|
@ -63,9 +69,13 @@ _PyBytes_FromSize(Py_ssize_t size, int use_calloc)
|
|||
PyBytesObject *op;
|
||||
assert(size >= 0);
|
||||
|
||||
if (size == 0 && (op = nullstring) != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
if (size == 0) {
|
||||
struct _Py_bytes_state *state = get_bytes_state();
|
||||
op = state->empty_string;
|
||||
if (op != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
}
|
||||
|
||||
if ((size_t)size > (size_t)PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
|
||||
|
@ -88,8 +98,9 @@ _PyBytes_FromSize(Py_ssize_t size, int use_calloc)
|
|||
op->ob_sval[size] = '\0';
|
||||
/* empty byte string singleton */
|
||||
if (size == 0) {
|
||||
nullstring = op;
|
||||
struct _Py_bytes_state *state = get_bytes_state();
|
||||
Py_INCREF(op);
|
||||
state->empty_string = op;
|
||||
}
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
@ -103,11 +114,13 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
|
|||
"Negative size passed to PyBytes_FromStringAndSize");
|
||||
return NULL;
|
||||
}
|
||||
if (size == 1 && str != NULL &&
|
||||
(op = characters[*str & UCHAR_MAX]) != NULL)
|
||||
{
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
if (size == 1 && str != NULL) {
|
||||
struct _Py_bytes_state *state = get_bytes_state();
|
||||
op = state->characters[*str & UCHAR_MAX];
|
||||
if (op != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
}
|
||||
|
||||
op = (PyBytesObject *)_PyBytes_FromSize(size, 0);
|
||||
|
@ -119,8 +132,9 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
|
|||
memcpy(op->ob_sval, str, size);
|
||||
/* share short strings */
|
||||
if (size == 1) {
|
||||
characters[*str & UCHAR_MAX] = op;
|
||||
struct _Py_bytes_state *state = get_bytes_state();
|
||||
Py_INCREF(op);
|
||||
state->characters[*str & UCHAR_MAX] = op;
|
||||
}
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
@ -138,13 +152,21 @@ PyBytes_FromString(const char *str)
|
|||
"byte string is too long");
|
||||
return NULL;
|
||||
}
|
||||
if (size == 0 && (op = nullstring) != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
|
||||
struct _Py_bytes_state *state = get_bytes_state();
|
||||
if (size == 0) {
|
||||
op = state->empty_string;
|
||||
if (op != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
}
|
||||
if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
else if (size == 1) {
|
||||
op = state->characters[*str & UCHAR_MAX];
|
||||
if (op != NULL) {
|
||||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inline PyObject_NewVar */
|
||||
|
@ -157,11 +179,12 @@ PyBytes_FromString(const char *str)
|
|||
memcpy(op->ob_sval, str, size+1);
|
||||
/* share short strings */
|
||||
if (size == 0) {
|
||||
nullstring = op;
|
||||
Py_INCREF(op);
|
||||
} else if (size == 1) {
|
||||
characters[*str & UCHAR_MAX] = op;
|
||||
state->empty_string = op;
|
||||
}
|
||||
else if (size == 1) {
|
||||
Py_INCREF(op);
|
||||
state->characters[*str & UCHAR_MAX] = op;
|
||||
}
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
@ -1249,6 +1272,8 @@ PyBytes_AsStringAndSize(PyObject *obj,
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* Methods */
|
||||
|
||||
#define STRINGLIB_GET_EMPTY() get_bytes_state()->empty_string
|
||||
|
||||
#include "stringlib/stringdefs.h"
|
||||
|
||||
#include "stringlib/fastsearch.h"
|
||||
|
@ -1261,6 +1286,8 @@ PyBytes_AsStringAndSize(PyObject *obj,
|
|||
|
||||
#include "stringlib/transmogrify.h"
|
||||
|
||||
#undef STRINGLIB_GET_EMPTY
|
||||
|
||||
PyObject *
|
||||
PyBytes_Repr(PyObject *obj, int smartquotes)
|
||||
{
|
||||
|
@ -3058,12 +3085,13 @@ error:
|
|||
}
|
||||
|
||||
void
|
||||
_PyBytes_Fini(void)
|
||||
_PyBytes_Fini(PyThreadState *tstate)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < UCHAR_MAX + 1; i++)
|
||||
Py_CLEAR(characters[i]);
|
||||
Py_CLEAR(nullstring);
|
||||
struct _Py_bytes_state* state = &tstate->interp->bytes;
|
||||
for (int i = 0; i < UCHAR_MAX + 1; i++) {
|
||||
Py_CLEAR(state->characters[i]);
|
||||
}
|
||||
Py_CLEAR(state->empty_string);
|
||||
}
|
||||
|
||||
/*********************** Bytes Iterator ****************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue