Skip to content

Commit 694506d

Browse files
Yhg1smeta-codesync[bot]
authored andcommitted
Move push_chunk from a borrow to a modified copy.
Summary: Move push_chunk from a borrow to a modified copy that incorporates upstream PR python/cpython#145828, gating the use of the new tstate member on a feature define so we can avoid using it unless we know the deploy target supports it. Reviewed By: DinoV Differential Revision: D96934356 fbshipit-source-id: 0f75b826d4663764bf9900ad155617d0a9b65e7d
1 parent fc137cd commit 694506d

2 files changed

Lines changed: 65 additions & 4 deletions

File tree

cinderx/UpstreamBorrow/borrowed-3.14.c.template

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,49 @@ error:
409409
// @Borrow CPP directives noinclude from Objects/obmalloc.c
410410
// @Borrow function _PyObject_VirtualAlloc from Objects/obmalloc.c
411411
// @Borrow function allocate_chunk from Python/pystate.c
412-
// @Borrow function push_chunk from Python/pystate.c
412+
413+
// Borrowed and patched to gate the use of tstate->datastack_cached_chunk on
414+
// a feature define, since Python 3.14.3 and earlier don't have that struct
415+
// member, and trying to use it would read out of bounds data.
416+
static PyObject **
417+
push_chunk(PyThreadState *tstate, int size)
418+
{
419+
int allocate_size = _PY_DATA_STACK_CHUNK_SIZE;
420+
while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) {
421+
allocate_size *= 2;
422+
}
423+
_PyStackChunk *new;
424+
#ifdef ENABLE_PYTHON_TSTATE_DATASTACK_CACHE
425+
if (tstate->datastack_cached_chunk != NULL
426+
&& (size_t)allocate_size <= tstate->datastack_cached_chunk->size)
427+
{
428+
new = tstate->datastack_cached_chunk;
429+
tstate->datastack_cached_chunk = NULL;
430+
new->previous = tstate->datastack_chunk;
431+
new->top = 0;
432+
}
433+
else
434+
#endif
435+
{
436+
new = allocate_chunk(allocate_size, tstate->datastack_chunk);
437+
if (new == NULL) {
438+
return NULL;
439+
}
440+
}
441+
if (tstate->datastack_chunk) {
442+
tstate->datastack_chunk->top = tstate->datastack_top -
443+
&tstate->datastack_chunk->data[0];
444+
}
445+
tstate->datastack_chunk = new;
446+
tstate->datastack_limit = (PyObject **)(((char *)new) + allocate_size);
447+
// When new is the "root" chunk (i.e. new->previous == NULL), we can keep
448+
// _PyThreadState_PopFrame from freeing it later by "skipping" over the
449+
// first element:
450+
PyObject **res = &new->data[new->previous == NULL];
451+
tstate->datastack_top = res + size;
452+
return res;
453+
}
454+
413455
// @Borrow function _PyThreadState_PushFrame from Python/pystate.c
414456

415457
void _PyErr_SetObject(PyThreadState* tstate, PyObject* type, PyObject* value) {

cinderx/UpstreamBorrow/borrowed-3.14.gen_cached.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3821,16 +3821,34 @@ allocate_chunk(int size_in_bytes, _PyStackChunk* previous)
38213821
res->top = 0;
38223822
return res;
38233823
}
3824+
3825+
// Borrowed and patched to gate the use of tstate->datastack_cached_chunk on
3826+
// a feature define, since Python 3.14.3 and earlier don't have that struct
3827+
// member, and trying to use it would read out of bounds data.
38243828
static PyObject **
38253829
push_chunk(PyThreadState *tstate, int size)
38263830
{
38273831
int allocate_size = _PY_DATA_STACK_CHUNK_SIZE;
38283832
while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) {
38293833
allocate_size *= 2;
38303834
}
3831-
_PyStackChunk *new = allocate_chunk(allocate_size, tstate->datastack_chunk);
3832-
if (new == NULL) {
3833-
return NULL;
3835+
_PyStackChunk *new;
3836+
#ifdef ENABLE_PYTHON_TSTATE_DATASTACK_CACHE
3837+
if (tstate->datastack_cached_chunk != NULL
3838+
&& (size_t)allocate_size <= tstate->datastack_cached_chunk->size)
3839+
{
3840+
new = tstate->datastack_cached_chunk;
3841+
tstate->datastack_cached_chunk = NULL;
3842+
new->previous = tstate->datastack_chunk;
3843+
new->top = 0;
3844+
}
3845+
else
3846+
#endif
3847+
{
3848+
new = allocate_chunk(allocate_size, tstate->datastack_chunk);
3849+
if (new == NULL) {
3850+
return NULL;
3851+
}
38343852
}
38353853
if (tstate->datastack_chunk) {
38363854
tstate->datastack_chunk->top = tstate->datastack_top -
@@ -3845,6 +3863,7 @@ push_chunk(PyThreadState *tstate, int size)
38453863
tstate->datastack_top = res + size;
38463864
return res;
38473865
}
3866+
38483867
_PyInterpreterFrame *
38493868
_PyThreadState_PushFrame(PyThreadState *tstate, size_t size)
38503869
{

0 commit comments

Comments
 (0)