Skip to content

Commit e692fee

Browse files
authored
Make hydration context a PyObject (python#47)
1 parent ae1cecc commit e692fee

File tree

4 files changed

+90
-16
lines changed

4 files changed

+90
-16
lines changed

Include/cpython/code.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ struct PyCodeObject {
110110
union _cache_or_instruction *co_quickened;
111111

112112
/* Hydration */
113-
struct context *co_hydra_context;
113+
struct hydration_context *co_hydra_context;
114114
Py_ssize_t co_hydra_offset;
115115
Py_ssize_t co_hydra_refs_pos;
116116

Include/internal/pycore_code.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ struct _PyCodeConstructor {
243243
PyObject *exceptiontable;
244244

245245
/* Hydration */
246-
struct context *hydra_context; // Hydration context
246+
struct hydration_context *hydra_context; // Hydration context
247247
Py_ssize_t hydra_offset; // Index in data stream where to start
248248
Py_ssize_t hydra_refs_pos; // Where to reset refs_pos
249249
};

Objects/codeobject.c

+2
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
364364
co->co_exceptiontable = con->exceptiontable;
365365

366366
/* hydration */
367+
Py_XINCREF(con->hydra_context);
367368
co->co_hydra_context = con->hydra_context;
368369
co->co_hydra_offset = con->hydra_offset;
369370
co->co_hydra_refs_pos = con->hydra_refs_pos;
@@ -1421,6 +1422,7 @@ code_dealloc(PyCodeObject *co)
14211422
Py_XDECREF(co->co_endlinetable);
14221423
Py_XDECREF(co->co_columntable);
14231424
Py_XDECREF(co->co_exceptiontable);
1425+
Py_XDECREF(co->co_hydra_context);
14241426
if (co->co_weakreflist != NULL)
14251427
PyObject_ClearWeakRefs((PyObject*)co);
14261428
if (co->co_quickened) {

Python/marshal.c

+86-14
Original file line numberDiff line numberDiff line change
@@ -660,14 +660,86 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
660660
w_flush(&wf);
661661
}
662662

663-
664-
struct context {
663+
typedef struct hydration_context {
664+
PyObject_HEAD
665665
PyObject *obj; // Python bytes(-like) object containing the data
666666
const char *buf; // Pointer to first byte
667667
Py_ssize_t len; // Number of bytes
668668
PyObject *refs; // List of shared values
669669
PyCodeObject *code; // If not NULL, code object to be updated
670670
// TODO: the latter is neither re-entrant nor thread-safe :-(
671+
} _PyHydrationContext;
672+
673+
static void
674+
hydration_ctx_dealloc(_PyHydrationContext *self)
675+
{
676+
Py_XDECREF(self->obj);
677+
Py_XDECREF(self->refs);
678+
Py_XDECREF(self->code);
679+
PyObject_Free(self);
680+
}
681+
682+
PyTypeObject _PyHydrationContext_Type;
683+
684+
_PyHydrationContext *
685+
_PyHydrationContext_new(
686+
PyObject *obj, char *s, Py_ssize_t n, PyObject *refs)
687+
{
688+
_PyHydrationContext *ctx = PyObject_New(
689+
_PyHydrationContext, &_PyHydrationContext_Type);
690+
if (ctx == NULL) {
691+
PyErr_NoMemory();
692+
return NULL;
693+
}
694+
Py_INCREF(obj);
695+
ctx->obj = obj;
696+
ctx->buf = s;
697+
ctx->len = n;
698+
ctx->code = NULL;
699+
Py_INCREF(refs);
700+
ctx->refs = refs;
701+
return ctx;
702+
}
703+
704+
PyTypeObject _PyHydrationContext_Type = {
705+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
706+
"HydrationContext",
707+
sizeof(_PyHydrationContext),
708+
0,
709+
(destructor)hydration_ctx_dealloc, /* tp_dealloc */
710+
0, /* tp_vectorcall_offset */
711+
0, /* tp_getattr */
712+
0, /* tp_setattr */
713+
0, /* tp_as_async */
714+
0, /* tp_repr */
715+
0, /* tp_as_number */
716+
0, /* tp_as_sequence */
717+
0, /* tp_as_mapping */
718+
0, /* tp_hash */
719+
0, /* tp_call */
720+
0, /* tp_str */
721+
0, /* tp_getattro */
722+
0, /* tp_setattro */
723+
0, /* tp_as_buffer */
724+
Py_TPFLAGS_DEFAULT, /* tp_flags */
725+
0, /* tp_doc */
726+
0, /* tp_traverse */
727+
0, /* tp_clear */
728+
0, /* tp_richcompare */
729+
0, /* tp_weaklistoffset */
730+
0, /* tp_iter */
731+
0, /* tp_iternext */
732+
0, /* tp_methods */
733+
0, /* tp_members */
734+
0, /* tp_getset */
735+
0, /* tp_base */
736+
0, /* tp_dict */
737+
0, /* tp_descr_get */
738+
0, /* tp_descr_set */
739+
0, /* tp_dictoffset */
740+
0, /* tp_init */
741+
0, /* tp_alloc */
742+
0, /* tp_new */
671743
};
672744

673745
typedef struct {
@@ -680,7 +752,7 @@ typedef struct {
680752
Py_ssize_t buf_size;
681753
PyObject *refs; /* a list */
682754
Py_ssize_t refs_pos; /* Where in refs to insert/append */
683-
struct context *ctx;
755+
_PyHydrationContext *ctx;
684756
} RFILE;
685757

686758
static const char *
@@ -1954,28 +2026,23 @@ marshal_loads_impl(PyObject *module, Py_buffer *bytes, int lazy)
19542026
if (lazy < 0)
19552027
lazy = getenv("LAZY") && *getenv("LAZY"); // TODO: Rename?
19562028
if (lazy) {
1957-
rf.ctx = PyMem_Malloc(sizeof(struct context));
2029+
rf.ctx = _PyHydrationContext_new(
2030+
bytes->obj, s, n, rf.refs);
19582031
if (rf.ctx == NULL) {
19592032
PyErr_NoMemory();
19602033
return NULL;
19612034
}
1962-
Py_INCREF(bytes->obj);
1963-
rf.ctx->obj = bytes->obj;
1964-
rf.ctx->buf = s;
1965-
rf.ctx->len = n;
1966-
rf.ctx->code = NULL;
1967-
Py_INCREF(rf.refs);
1968-
rf.ctx->refs = rf.refs;
19692035
}
19702036
result = read_object(&rf);
1971-
Py_DECREF(rf.refs);
2037+
Py_XDECREF(rf.ctx);
2038+
Py_XDECREF(rf.refs);
19722039
return result;
19732040
}
19742041

19752042
PyCodeObject *
19762043
_PyCode_Hydrate(PyCodeObject *code)
19772044
{
1978-
struct context *ctx = code->co_hydra_context;
2045+
_PyHydrationContext *ctx = code->co_hydra_context;
19792046
if (ctx == NULL) {
19802047
// Not dehydrated
19812048
assert(_PyCode_IsHydrated(code));
@@ -1998,12 +2065,17 @@ _PyCode_Hydrate(PyCodeObject *code)
19982065
rf.end = s + n;
19992066
rf.depth = 0;
20002067
rf.refs = ctx->refs;
2068+
Py_XINCREF(rf.refs);
20012069
rf.refs_pos = code->co_hydra_refs_pos;
20022070
rf.ctx = ctx;
2071+
Py_INCREF(code);
20032072
ctx->code = code;
20042073

20052074
PyObject *result = read_object(&rf);
2006-
2075+
Py_XDECREF(rf.refs);
2076+
Py_XDECREF(code->co_hydra_context);
2077+
code->co_hydra_context = NULL;
2078+
Py_XDECREF(ctx->code);
20072079
ctx->code = NULL;
20082080
assert(result == NULL || PyCode_Check(result));
20092081
return (PyCodeObject *)result;

0 commit comments

Comments
 (0)