Skip to content

Commit bfc2286

Browse files
committed
Streamline PyObject_Malloc and PyObject_Free. Use the fast variants in more places
1 parent 83ebcf5 commit bfc2286

File tree

8 files changed

+76
-71
lines changed

8 files changed

+76
-71
lines changed

Objects/bytesobject.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ _PyBytes_FromSize(Py_ssize_t size, int use_calloc)
9393
if (use_calloc)
9494
op = (PyBytesObject *)PyObject_Calloc(1, PyBytesObject_SIZE + size);
9595
else
96-
op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + size);
96+
op = (PyBytesObject *)_PyObject_MallocFast(PyBytesObject_SIZE + size);
9797
if (op == NULL) {
9898
return PyErr_NoMemory();
9999
}
@@ -160,7 +160,7 @@ PyBytes_FromString(const char *str)
160160
}
161161

162162
/* Inline PyObject_NewVar */
163-
op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + size);
163+
op = (PyBytesObject *)_PyObject_MallocFast(PyBytesObject_SIZE + size);
164164
if (op == NULL) {
165165
return PyErr_NoMemory();
166166
}
@@ -1470,7 +1470,7 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n)
14701470
"repeated bytes are too long");
14711471
return NULL;
14721472
}
1473-
op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + nbytes);
1473+
op = (PyBytesObject *)_PyObject_MallocFast(PyBytesObject_SIZE + nbytes);
14741474
if (op == NULL) {
14751475
return PyErr_NoMemory();
14761476
}

Objects/codeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,7 @@ code_dealloc(PyCodeObject *co)
17491749
PyObject_ClearWeakRefs((PyObject*)co);
17501750
}
17511751
free_monitoring_data(co->_co_monitoring);
1752-
PyObject_Free(co);
1752+
_PyObject_FreeFast(co);
17531753
}
17541754

17551755
static PyObject *

Objects/floatobject.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ PyFloat_FromDouble(double fval)
144144
else
145145
#endif
146146
{
147-
op = PyObject_Malloc(sizeof(PyFloatObject));
147+
op = _PyObject_MallocFast(sizeof(PyFloatObject));
148148
if (!op) {
149149
return PyErr_NoMemory();
150150
}
@@ -252,15 +252,15 @@ _PyFloat_ExactDealloc(PyObject *obj)
252252
#ifdef WITH_FREELISTS
253253
struct _Py_float_freelist *float_freelist = get_float_freelist();
254254
if (float_freelist->numfree >= PyFloat_MAXFREELIST || float_freelist->numfree < 0) {
255-
PyObject_Free(op);
255+
_PyObject_FreeFast(op);
256256
return;
257257
}
258258
float_freelist->numfree++;
259259
Py_SET_TYPE(op, (PyTypeObject *)float_freelist->items);
260260
float_freelist->items = op;
261261
OBJECT_STAT_INC(to_freelist);
262262
#else
263-
PyObject_Free(op);
263+
_PyObject_FreeFast(op);
264264
#endif
265265
}
266266

Objects/object.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
448448
PyObject *
449449
_PyObject_New(PyTypeObject *tp)
450450
{
451-
PyObject *op = (PyObject *) PyObject_Malloc(_PyObject_SIZE(tp));
451+
PyObject *op = (PyObject *) _PyObject_MallocFast(_PyObject_SIZE(tp));
452452
if (op == NULL) {
453453
return PyErr_NoMemory();
454454
}
@@ -461,7 +461,7 @@ _PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
461461
{
462462
PyVarObject *op;
463463
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
464-
op = (PyVarObject *) PyObject_Malloc(size);
464+
op = (PyVarObject *) _PyObject_MallocFast(size);
465465
if (op == NULL) {
466466
return (PyVarObject *)PyErr_NoMemory();
467467
}

Objects/obmalloc.c

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,19 +1281,6 @@ _PyMem_FiniDelayed(PyInterpreterState *interp)
12811281
/* the "object" allocator */
12821282
/**************************/
12831283

1284-
void *
1285-
PyObject_Malloc(size_t size)
1286-
{
1287-
/* see PyMem_RawMalloc() */
1288-
if (size > (size_t)PY_SSIZE_T_MAX)
1289-
return NULL;
1290-
OBJECT_STAT_INC_COND(allocations512, size < 512);
1291-
OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094);
1292-
OBJECT_STAT_INC_COND(allocations_big, size >= 4094);
1293-
OBJECT_STAT_INC(allocations);
1294-
return _PyObject.malloc(_PyObject.ctx, size);
1295-
}
1296-
12971284
void *
12981285
PyObject_Calloc(size_t nelem, size_t elsize)
12991286
{
@@ -1316,14 +1303,6 @@ PyObject_Realloc(void *ptr, size_t new_size)
13161303
return _PyObject.realloc(_PyObject.ctx, ptr, new_size);
13171304
}
13181305

1319-
void
1320-
PyObject_Free(void *ptr)
1321-
{
1322-
OBJECT_STAT_INC(frees);
1323-
_PyObject.free(_PyObject.ctx, ptr);
1324-
}
1325-
1326-
13271306
/* If we're using GCC, use __builtin_expect() to reduce overhead of
13281307
the valgrind checks */
13291308
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
@@ -2084,9 +2063,7 @@ pymalloc_alloc(OMState *state, void *Py_UNUSED(ctx), size_t nbytes)
20842063
}
20852064
#endif
20862065

2087-
if (UNLIKELY(nbytes == 0)) {
2088-
return NULL;
2089-
}
2066+
assert(nbytes != 0 && nbytes <= (size_t)PY_SSIZE_T_MAX/2);
20902067
if (UNLIKELY(nbytes > SMALL_REQUEST_THRESHOLD)) {
20912068
return NULL;
20922069
}
@@ -2119,17 +2096,23 @@ pymalloc_alloc(OMState *state, void *Py_UNUSED(ctx), size_t nbytes)
21192096
return (void *)bp;
21202097
}
21212098

2099+
static inline bool
2100+
zero_or_too_large(size_t nbytes)
2101+
{
2102+
return (nbytes-1) >= (size_t)PY_SSIZE_T_MAX;
2103+
}
21222104

21232105
void *
21242106
_PyObject_Malloc(void *ctx, size_t nbytes)
21252107
{
21262108
OMState *state = get_state();
2127-
void* ptr = pymalloc_alloc(state, ctx, nbytes);
2128-
if (LIKELY(ptr != NULL)) {
2129-
return ptr;
2109+
if (LIKELY(!zero_or_too_large(nbytes))) {
2110+
void* ptr = pymalloc_alloc(state, ctx, nbytes);
2111+
if (LIKELY(ptr != NULL)) {
2112+
return ptr;
2113+
}
21302114
}
2131-
2132-
ptr = PyMem_RawMalloc(nbytes);
2115+
void* ptr = PyMem_RawMalloc(nbytes);
21332116
if (ptr != NULL) {
21342117
raw_allocated_blocks++;
21352118
}
@@ -2144,13 +2127,14 @@ _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
21442127
size_t nbytes = nelem * elsize;
21452128

21462129
OMState *state = get_state();
2147-
void* ptr = pymalloc_alloc(state, ctx, nbytes);
2148-
if (LIKELY(ptr != NULL)) {
2149-
memset(ptr, 0, nbytes);
2150-
return ptr;
2130+
if (LIKELY(!zero_or_too_large(nbytes))) {
2131+
void *ptr = pymalloc_alloc(state, ctx, nbytes);
2132+
if (LIKELY(ptr != NULL)) {
2133+
memset(ptr, 0, nbytes);
2134+
return ptr;
2135+
}
21512136
}
2152-
2153-
ptr = PyMem_RawCalloc(nelem, elsize);
2137+
void *ptr = PyMem_RawCalloc(nelem, elsize);
21542138
if (ptr != NULL) {
21552139
raw_allocated_blocks++;
21562140
}
@@ -3449,14 +3433,14 @@ _PyObject_DebugMallocStats(FILE *out)
34493433
void *
34503434
_PyObject_MallocFast(size_t size)
34513435
{
3452-
assert(size != 0);
3436+
assert(!zero_or_too_large(size));
34533437
OBJECT_STAT_INC_COND(allocations512, size < 512);
34543438
OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094);
34553439
OBJECT_STAT_INC_COND(allocations_big, size >= 4094);
34563440
OBJECT_STAT_INC(allocations);
34573441
if (_PyObject.malloc == _PyObject_Malloc) {
34583442
OMState *state = get_state();
3459-
void* ptr = pymalloc_alloc(state, NULL, size);
3443+
void *ptr = pymalloc_alloc(state, NULL, size);
34603444
if (LIKELY(ptr != NULL)) {
34613445
return ptr;
34623446
}
@@ -3469,10 +3453,22 @@ _PyObject_MallocFast(size_t size)
34693453
return _PyObject.malloc(_PyObject.ctx, size);
34703454
}
34713455

3456+
void *
3457+
PyObject_Malloc(size_t size)
3458+
{
3459+
if (LIKELY(!zero_or_too_large(size))) {
3460+
return _PyObject_MallocFast(size);
3461+
}
3462+
if (size == 0) {
3463+
return _PyObject.malloc(_PyObject.ctx, 0);
3464+
}
3465+
return NULL;
3466+
}
3467+
34723468
void
34733469
_PyObject_FreeFast(void *ptr)
34743470
{
3475-
/* PyObject_Free(NULL) has no effect */
3471+
/* Don't check for NULL */
34763472
assert(ptr != NULL);
34773473
OBJECT_STAT_INC(frees);
34783474
if (_PyObject.free == _PyObject_Free) {
@@ -3488,5 +3484,14 @@ _PyObject_FreeFast(void *ptr)
34883484
}
34893485
}
34903486

3487+
void
3488+
PyObject_Free(void *ptr)
3489+
{
3490+
if (ptr == NULL) {
3491+
return;
3492+
}
3493+
_PyObject_FreeFast(ptr);
3494+
}
3495+
34913496

34923497
#endif /* #ifdef WITH_PYMALLOC */

Python/bytecodes.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -427,24 +427,24 @@ dummy_func(
427427
pure op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
428428
STAT_INC(BINARY_OP, hit);
429429
res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
430-
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
431-
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
430+
_Py_DECREF_SPECIALIZED(right, (destructor)_PyObject_FreeFast);
431+
_Py_DECREF_SPECIALIZED(left, (destructor)_PyObject_FreeFast);
432432
ERROR_IF(res == NULL, error);
433433
}
434434

435435
pure op(_BINARY_OP_ADD_INT, (left, right -- res)) {
436436
STAT_INC(BINARY_OP, hit);
437437
res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
438-
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
439-
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
438+
_Py_DECREF_SPECIALIZED(right, (destructor)_PyObject_FreeFast);
439+
_Py_DECREF_SPECIALIZED(left, (destructor)_PyObject_FreeFast);
440440
ERROR_IF(res == NULL, error);
441441
}
442442

443443
pure op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
444444
STAT_INC(BINARY_OP, hit);
445445
res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
446-
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
447-
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
446+
_Py_DECREF_SPECIALIZED(right, (destructor)_PyObject_FreeFast);
447+
_Py_DECREF_SPECIALIZED(left, (destructor)_PyObject_FreeFast);
448448
ERROR_IF(res == NULL, error);
449449
}
450450

@@ -612,7 +612,7 @@ dummy_func(
612612
res = PyList_GET_ITEM(list, index);
613613
assert(res != NULL);
614614
Py_INCREF(res);
615-
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
615+
_Py_DECREF_SPECIALIZED(sub, (destructor)_PyObject_FreeFast);
616616
Py_DECREF(list);
617617
}
618618

@@ -627,7 +627,7 @@ dummy_func(
627627
DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c);
628628
STAT_INC(BINARY_SUBSCR, hit);
629629
res = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
630-
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
630+
_Py_DECREF_SPECIALIZED(sub, (destructor)_PyObject_FreeFast);
631631
Py_DECREF(str);
632632
}
633633

Python/executor_cases.c.h

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)