Skip to content

Commit 4b4bcfb

Browse files
committed
Reimplement _PyBytes_Resize() via _PyBytes_ResizeKeepOnError()
For the in-place resize code path, no longer call _Py_ForgetReference() and _PyReftracerTrack() before PyObject_Realloc().
1 parent a1e64d3 commit 4b4bcfb

1 file changed

Lines changed: 18 additions & 32 deletions

File tree

Objects/bytesobject.c

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3344,15 +3344,16 @@ PyBytes_ConcatAndDel(PyObject **pv, PyObject *w)
33443344
does *not* include that), and a trailing \0 byte is stored.
33453345
*/
33463346

3347-
static int
3348-
bytes_resize(PyObject **pv, Py_ssize_t newsize, int clear_obj_on_error)
3347+
// Similar to _PyBytes_Resize(), but leaves the object unchanged on error.
3348+
int
3349+
_PyBytes_ResizeKeepOnError(PyObject **pv, Py_ssize_t newsize)
33493350
{
33503351
PyObject *v = *pv;
33513352
PyObject *result;
33523353

33533354
if (!PyBytes_Check(v) || newsize < 0) {
33543355
PyErr_BadInternalCall();
3355-
goto error;
3356+
return -1;
33563357
}
33573358

33583359
Py_ssize_t oldsize = PyBytes_GET_SIZE(v);
@@ -3364,7 +3365,7 @@ bytes_resize(PyObject **pv, Py_ssize_t newsize, int clear_obj_on_error)
33643365
if (oldsize == 0) {
33653366
result = _PyBytes_FromSize(newsize, 0);
33663367
if (result == NULL) {
3367-
goto error;
3368+
return -1;
33683369
}
33693370
*pv = result;
33703371
Py_DECREF(v);
@@ -3380,7 +3381,7 @@ bytes_resize(PyObject **pv, Py_ssize_t newsize, int clear_obj_on_error)
33803381
if (!_PyObject_IsUniquelyReferenced(v)) {
33813382
result = _PyBytes_FromSize(newsize, 0);
33823383
if (!result) {
3383-
goto error;
3384+
return -1;
33843385
}
33853386

33863387
memcpy(PyBytes_AS_STRING(result), PyBytes_AS_STRING(v), Py_MIN(oldsize, newsize));
@@ -3390,23 +3391,17 @@ bytes_resize(PyObject **pv, Py_ssize_t newsize, int clear_obj_on_error)
33903391
}
33913392

33923393
assert(v != bytes_get_empty());
3393-
#ifdef Py_TRACE_REFS
3394-
_Py_ForgetReference(v);
3395-
#endif
3396-
_PyReftracerTrack(v, PyRefTracer_DESTROY);
33973394
result = (PyObject *)PyObject_Realloc(v, PyBytesObject_SIZE + newsize);
33983395
if (result == NULL) {
3399-
if (clear_obj_on_error) {
3400-
*pv = NULL;
3401-
#ifdef Py_REF_DEBUG
3402-
_Py_DecRefTotal(_PyThreadState_GET());
3403-
#endif
3404-
PyObject_Free(v);
3405-
}
34063396
PyErr_NoMemory();
34073397
return -1;
34083398
}
34093399

3400+
#ifdef Py_TRACE_REFS
3401+
_Py_ForgetReference(v);
3402+
#endif
3403+
_PyReftracerTrack(v, PyRefTracer_DESTROY);
3404+
34103405
v = result;
34113406
_Py_NewReferenceNoTotal(v);
34123407
PyBytesObject *sv = (PyBytesObject *)v;
@@ -3415,28 +3410,19 @@ bytes_resize(PyObject **pv, Py_ssize_t newsize, int clear_obj_on_error)
34153410
set_ob_shash(sv, -1); /* invalidate cached hash value */
34163411
*pv = v;
34173412
return 0;
3418-
3419-
error:
3420-
if (clear_obj_on_error) {
3421-
*pv = NULL;
3422-
Py_DECREF(v);
3423-
}
3424-
return -1;
34253413
}
34263414

34273415

34283416
int
34293417
_PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
34303418
{
3431-
return bytes_resize(pv, newsize, 1);
3432-
}
3433-
3434-
3435-
// Similar to _PyBytes_Resize(), but leaves the object unchanged on error.
3436-
int
3437-
_PyBytes_ResizeKeepOnError(PyObject **pv, Py_ssize_t newsize)
3438-
{
3439-
return bytes_resize(pv, newsize, 0);
3419+
int res = _PyBytes_ResizeKeepOnError(pv, newsize);
3420+
if (res < 0) {
3421+
PyObject *v = *pv;
3422+
*pv = NULL;
3423+
Py_DECREF(v);
3424+
}
3425+
return res;
34403426
}
34413427

34423428

0 commit comments

Comments
 (0)