Commit dc1f1d6c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Unicode gc fix

Since we don't memset the unicode allocations any more, and
we now use a precise gc handler, we have to be careful that
unicode objects are valid enough whenever a collection could
happen.

The issue was that "unicode->str = gc_alloc(...)" could cause
a collection, in which case the collector would go and see a
bogus value in the ->str field.  Now, do the str allocation
first (since it is UNTRACKED) and then do the precise allocation
second.
parent d8f36db5
......@@ -2873,6 +2873,13 @@ extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
return (PyUnicodeObject*)PyErr_NoMemory();
}
// Pyston change: allocate ->str first, so that if this allocation
// causes a collection, we don't see a half-created unicode object:
size_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);
Py_UNICODE* str = (Py_UNICODE*)gc_alloc(new_size, gc::GCKind::UNTRACKED);
if (!str)
return (PyUnicodeObject*)PyErr_NoMemory();
// Do a bunch of inlining + constant folding of this line of CPython's:
// unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);
assert(PyUnicode_Type.tp_basicsize == sizeof(PyUnicodeObject)); // use the compile-time constant
......@@ -2886,13 +2893,7 @@ extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
assert(!PyUnicode_Type.instancesHaveDictAttrs());
unicode->ob_type = (struct _typeobject*)&PyUnicode_Type;
size_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);
unicode->str = (Py_UNICODE*)gc_alloc(new_size, gc::GCKind::UNTRACKED);
if (!unicode->str) {
PyErr_NoMemory();
goto onError;
}
unicode->str = str;
/* Initialize the first element to guard against cases where
* the caller fails before initializing str -- unicode_resize()
......@@ -2907,13 +2908,6 @@ extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
unicode->hash = -1;
unicode->defenc = NULL;
return unicode;
onError:
/* XXX UNREF/NEWREF interface should be more symmetrical */
_Py_DEC_REFTOTAL;
_Py_ForgetReference((PyObject*)unicode);
PyObject_Del(unicode);
return NULL;
}
bool TRACK_ALLOCATIONS = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment