summaryrefslogtreecommitdiffstats
path: root/Objects/bytesobject.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-06-23 13:54:35 (GMT)
committerGitHub <noreply@github.com>2020-06-23 13:54:35 (GMT)
commitc41eed1a874e2f22bde45c3c89418414b7a37f46 (patch)
treee90ff0bf1c5349169f3f04c914695b3c4b476f37 /Objects/bytesobject.c
parent32f2eda85957365d208f499b730d30b7eb419741 (diff)
downloadcpython-c41eed1a874e2f22bde45c3c89418414b7a37f46.zip
cpython-c41eed1a874e2f22bde45c3c89418414b7a37f46.tar.gz
cpython-c41eed1a874e2f22bde45c3c89418414b7a37f46.tar.bz2
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.
Diffstat (limited to 'Objects/bytesobject.c')
-rw-r--r--Objects/bytesobject.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index d397214..ce006e1 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -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 ****************************/