Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Python/crossinterp_data_lookup.h
Line
Count
Source (jump to first uncovered line)
1
#include "pycore_weakref.h"       // _PyWeakref_GET_REF()
2
3
4
typedef struct _dlcontext {
5
    _PyXIData_lookup_t *global;
6
    _PyXIData_lookup_t *local;
7
} dlcontext_t;
8
typedef _PyXIData_registry_t dlregistry_t;
9
typedef _PyXIData_regitem_t dlregitem_t;
10
11
12
// forward
13
static void _xidregistry_init(dlregistry_t *);
14
static void _xidregistry_fini(dlregistry_t *);
15
static _PyXIData_getdata_t _lookup_getdata_from_registry(
16
                                            dlcontext_t *, PyObject *);
17
18
19
/* used in crossinterp.c */
20
21
static void
22
xid_lookup_init(_PyXIData_lookup_t *state)
23
32
{
24
32
    _xidregistry_init(&state->registry);
25
32
}
26
27
static void
28
xid_lookup_fini(_PyXIData_lookup_t *state)
29
0
{
30
0
    _xidregistry_fini(&state->registry);
31
0
}
32
33
static int
34
get_lookup_context(PyThreadState *tstate, dlcontext_t *res)
35
0
{
36
0
    _PyXI_global_state_t *global = _PyXI_GET_GLOBAL_STATE(tstate->interp);
37
0
    if (global == NULL) {
38
0
        assert(PyErr_Occurred());
39
0
        return -1;
40
0
    }
41
0
    _PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp);
42
0
    if (local == NULL) {
43
0
        assert(PyErr_Occurred());
44
0
        return -1;
45
0
    }
46
0
    *res = (dlcontext_t){
47
0
        .global = &global->data_lookup,
48
0
        .local = &local->data_lookup,
49
0
    };
50
0
    return 0;
51
0
}
52
53
static _PyXIData_getdata_t
54
lookup_getdata(dlcontext_t *ctx, PyObject *obj)
55
0
{
56
   /* Cross-interpreter objects are looked up by exact match on the class.
57
      We can reassess this policy when we move from a global registry to a
58
      tp_* slot. */
59
0
    return _lookup_getdata_from_registry(ctx, obj);
60
0
}
61
62
63
/* exported API */
64
65
PyObject *
66
_PyXIData_GetNotShareableErrorType(PyThreadState *tstate)
67
0
{
68
0
    PyObject *exctype = get_notshareableerror_type(tstate);
69
0
    assert(exctype != NULL);
70
0
    return exctype;
71
0
}
72
73
void
74
_PyXIData_SetNotShareableError(PyThreadState *tstate, const char *msg)
75
0
{
76
0
    PyObject *cause = NULL;
77
0
    set_notshareableerror(tstate, cause, 1, msg);
78
0
}
79
80
void
81
_PyXIData_FormatNotShareableError(PyThreadState *tstate,
82
                                  const char *format, ...)
83
0
{
84
0
    PyObject *cause = NULL;
85
0
    va_list vargs;
86
0
    va_start(vargs, format);
87
0
    format_notshareableerror_v(tstate, cause, 1, format, vargs);
88
0
    va_end(vargs);
89
0
}
90
91
int
92
_PyXI_UnwrapNotShareableError(PyThreadState * tstate, _PyXI_failure *failure)
93
0
{
94
0
    PyObject *exctype = get_notshareableerror_type(tstate);
95
0
    assert(exctype != NULL);
96
0
    if (!_PyErr_ExceptionMatches(tstate, exctype)) {
97
0
        return -1;
98
0
    }
99
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
100
0
    if (failure != NULL) {
101
0
        _PyXI_errcode code = _PyXI_ERR_NOT_SHAREABLE;
102
0
        if (_PyXI_InitFailure(failure, code, exc) < 0) {
103
0
            return -1;
104
0
        }
105
0
    }
106
0
    PyObject *cause = PyException_GetCause(exc);
107
0
    if (cause != NULL) {
108
0
        Py_DECREF(exc);
109
0
        exc = cause;
110
0
    }
111
0
    else {
112
0
        assert(PyException_GetContext(exc) == NULL);
113
0
    }
114
0
    _PyErr_SetRaisedException(tstate, exc);
115
0
    return 0;
116
0
}
117
118
119
_PyXIData_getdata_t
120
_PyXIData_Lookup(PyThreadState *tstate, PyObject *obj)
121
0
{
122
0
    dlcontext_t ctx;
123
0
    if (get_lookup_context(tstate, &ctx) < 0) {
124
0
        return (_PyXIData_getdata_t){0};
125
0
    }
126
0
    return lookup_getdata(&ctx, obj);
127
0
}
128
129
130
/***********************************************/
131
/* a registry of {type -> _PyXIData_getdata_t} */
132
/***********************************************/
133
134
/* For now we use a global registry of shareable classes.
135
   An alternative would be to add a tp_* slot for a class's
136
   _PyXIData_getdata_t.  It would be simpler and more efficient. */
137
138
139
/* registry lifecycle */
140
141
static void _register_builtins_for_crossinterpreter_data(dlregistry_t *);
142
143
static void
144
_xidregistry_init(dlregistry_t *registry)
145
32
{
146
32
    if (registry->initialized) {
147
0
        return;
148
0
    }
149
32
    registry->initialized = 1;
150
151
32
    if (registry->global) {
152
        // Registering the builtins is cheap so we don't bother doing it lazily.
153
16
        assert(registry->head == NULL);
154
16
        _register_builtins_for_crossinterpreter_data(registry);
155
16
    }
156
32
}
157
158
static void _xidregistry_clear(dlregistry_t *);
159
160
static void
161
_xidregistry_fini(dlregistry_t *registry)
162
0
{
163
0
    if (!registry->initialized) {
164
0
        return;
165
0
    }
166
0
    registry->initialized = 0;
167
168
0
    _xidregistry_clear(registry);
169
0
}
170
171
172
/* registry thread safety */
173
174
static void
175
_xidregistry_lock(dlregistry_t *registry)
176
0
{
177
0
    if (registry->global) {
178
0
        PyMutex_Lock(&registry->mutex);
179
0
    }
180
    // else: Within an interpreter we rely on the GIL instead of a separate lock.
181
0
}
182
183
static void
184
_xidregistry_unlock(dlregistry_t *registry)
185
0
{
186
0
    if (registry->global) {
187
0
        PyMutex_Unlock(&registry->mutex);
188
0
    }
189
0
}
190
191
192
/* accessing the registry */
193
194
static inline dlregistry_t *
195
_get_xidregistry_for_type(dlcontext_t *ctx, PyTypeObject *cls)
196
0
{
197
0
    if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
198
0
        return &ctx->local->registry;
199
0
    }
200
0
    return &ctx->global->registry;
201
0
}
202
203
static dlregitem_t* _xidregistry_remove_entry(dlregistry_t *, dlregitem_t *);
204
205
static dlregitem_t *
206
_xidregistry_find_type(dlregistry_t *xidregistry, PyTypeObject *cls)
207
0
{
208
0
    dlregitem_t *cur = xidregistry->head;
209
0
    while (cur != NULL) {
210
0
        if (cur->weakref != NULL) {
211
            // cur is/was a heap type.
212
0
            PyObject *registered = _PyWeakref_GET_REF(cur->weakref);
213
0
            if (registered == NULL) {
214
                // The weakly ref'ed object was freed.
215
0
                cur = _xidregistry_remove_entry(xidregistry, cur);
216
0
                continue;
217
0
            }
218
0
            assert(PyType_Check(registered));
219
0
            assert(cur->cls == (PyTypeObject *)registered);
220
0
            assert(cur->cls->tp_flags & Py_TPFLAGS_HEAPTYPE);
221
0
            Py_DECREF(registered);
222
0
        }
223
0
        if (cur->cls == cls) {
224
0
            return cur;
225
0
        }
226
0
        cur = cur->next;
227
0
    }
228
0
    return NULL;
229
0
}
230
231
static _PyXIData_getdata_t
232
_lookup_getdata_from_registry(dlcontext_t *ctx, PyObject *obj)
233
0
{
234
0
    PyTypeObject *cls = Py_TYPE(obj);
235
236
0
    dlregistry_t *xidregistry = _get_xidregistry_for_type(ctx, cls);
237
0
    _xidregistry_lock(xidregistry);
238
239
0
    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
240
0
    _PyXIData_getdata_t getdata = matched != NULL
241
0
        ? matched->getdata
242
0
        : (_PyXIData_getdata_t){0};
243
244
0
    _xidregistry_unlock(xidregistry);
245
0
    return getdata;
246
0
}
247
248
249
/* updating the registry */
250
251
static int
252
_xidregistry_add_type(dlregistry_t *xidregistry,
253
                      PyTypeObject *cls, _PyXIData_getdata_t getdata)
254
112
{
255
112
    dlregitem_t *newhead = PyMem_RawMalloc(sizeof(dlregitem_t));
256
112
    if (newhead == NULL) {
257
0
        return -1;
258
0
    }
259
112
    assert((getdata.basic == NULL) != (getdata.fallback == NULL));
260
112
    *newhead = (dlregitem_t){
261
        // We do not keep a reference, to avoid keeping the class alive.
262
112
        .cls = cls,
263
112
        .refcount = 1,
264
112
        .getdata = getdata,
265
112
    };
266
112
    if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
267
        // XXX Assign a callback to clear the entry from the registry?
268
0
        newhead->weakref = PyWeakref_NewRef((PyObject *)cls, NULL);
269
0
        if (newhead->weakref == NULL) {
270
0
            PyMem_RawFree(newhead);
271
0
            return -1;
272
0
        }
273
0
    }
274
112
    newhead->next = xidregistry->head;
275
112
    if (newhead->next != NULL) {
276
96
        newhead->next->prev = newhead;
277
96
    }
278
112
    xidregistry->head = newhead;
279
112
    return 0;
280
112
}
281
282
static dlregitem_t *
283
_xidregistry_remove_entry(dlregistry_t *xidregistry, dlregitem_t *entry)
284
0
{
285
0
    dlregitem_t *next = entry->next;
286
0
    if (entry->prev != NULL) {
287
0
        assert(entry->prev->next == entry);
288
0
        entry->prev->next = next;
289
0
    }
290
0
    else {
291
0
        assert(xidregistry->head == entry);
292
0
        xidregistry->head = next;
293
0
    }
294
0
    if (next != NULL) {
295
0
        next->prev = entry->prev;
296
0
    }
297
0
    Py_XDECREF(entry->weakref);
298
0
    PyMem_RawFree(entry);
299
0
    return next;
300
0
}
301
302
static void
303
_xidregistry_clear(dlregistry_t *xidregistry)
304
0
{
305
0
    dlregitem_t *cur = xidregistry->head;
306
0
    xidregistry->head = NULL;
307
0
    while (cur != NULL) {
308
0
        dlregitem_t *next = cur->next;
309
0
        Py_XDECREF(cur->weakref);
310
0
        PyMem_RawFree(cur);
311
0
        cur = next;
312
0
    }
313
0
}
314
315
int
316
_PyXIData_RegisterClass(PyThreadState *tstate,
317
                        PyTypeObject *cls, _PyXIData_getdata_t getdata)
318
0
{
319
0
    if (!PyType_Check(cls)) {
320
0
        PyErr_Format(PyExc_ValueError, "only classes may be registered");
321
0
        return -1;
322
0
    }
323
0
    if (getdata.basic == NULL && getdata.fallback == NULL) {
324
0
        PyErr_Format(PyExc_ValueError, "missing 'getdata' func");
325
0
        return -1;
326
0
    }
327
328
0
    int res = 0;
329
0
    dlcontext_t ctx;
330
0
    if (get_lookup_context(tstate, &ctx) < 0) {
331
0
        return -1;
332
0
    }
333
0
    dlregistry_t *xidregistry = _get_xidregistry_for_type(&ctx, cls);
334
0
    _xidregistry_lock(xidregistry);
335
336
0
    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
337
0
    if (matched != NULL) {
338
0
        assert(matched->getdata.basic == getdata.basic);
339
0
        assert(matched->getdata.fallback == getdata.fallback);
340
0
        matched->refcount += 1;
341
0
        goto finally;
342
0
    }
343
344
0
    res = _xidregistry_add_type(xidregistry, cls, getdata);
345
346
0
finally:
347
0
    _xidregistry_unlock(xidregistry);
348
0
    return res;
349
0
}
350
351
int
352
_PyXIData_UnregisterClass(PyThreadState *tstate, PyTypeObject *cls)
353
0
{
354
0
    int res = 0;
355
0
    dlcontext_t ctx;
356
0
    if (get_lookup_context(tstate, &ctx) < 0) {
357
0
        return -1;
358
0
    }
359
0
    dlregistry_t *xidregistry = _get_xidregistry_for_type(&ctx, cls);
360
0
    _xidregistry_lock(xidregistry);
361
362
0
    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
363
0
    if (matched != NULL) {
364
0
        assert(matched->refcount > 0);
365
0
        matched->refcount -= 1;
366
0
        if (matched->refcount == 0) {
367
0
            (void)_xidregistry_remove_entry(xidregistry, matched);
368
0
        }
369
0
        res = 1;
370
0
    }
371
372
0
    _xidregistry_unlock(xidregistry);
373
0
    return res;
374
0
}
375
376
377
/********************************************/
378
/* cross-interpreter data for builtin types */
379
/********************************************/
380
381
// bytes
382
383
int
384
_PyBytes_GetData(PyObject *obj, _PyBytes_data_t *data)
385
0
{
386
0
    if (!PyBytes_Check(obj)) {
387
0
        PyErr_Format(PyExc_TypeError, "expected bytes, got %R", obj);
388
0
        return -1;
389
0
    }
390
0
    char *bytes;
391
0
    Py_ssize_t len;
392
0
    if (PyBytes_AsStringAndSize(obj, &bytes, &len) < 0) {
393
0
        return -1;
394
0
    }
395
0
    *data = (_PyBytes_data_t){
396
0
        .bytes = bytes,
397
0
        .len = len,
398
0
    };
399
0
    return 0;
400
0
}
401
402
PyObject *
403
_PyBytes_FromData(_PyBytes_data_t *data)
404
0
{
405
0
    return PyBytes_FromStringAndSize(data->bytes, data->len);
406
0
}
407
408
PyObject *
409
_PyBytes_FromXIData(_PyXIData_t *xidata)
410
0
{
411
0
    _PyBytes_data_t *data = (_PyBytes_data_t *)xidata->data;
412
0
    assert(_PyXIData_OBJ(xidata) != NULL
413
0
            && PyBytes_Check(_PyXIData_OBJ(xidata)));
414
0
    return _PyBytes_FromData(data);
415
0
}
416
417
static int
418
_bytes_shared(PyThreadState *tstate,
419
              PyObject *obj, size_t size, xid_newobjfunc newfunc,
420
              _PyXIData_t *xidata)
421
0
{
422
0
    assert(size >= sizeof(_PyBytes_data_t));
423
0
    assert(newfunc != NULL);
424
0
    if (_PyXIData_InitWithSize(
425
0
                        xidata, tstate->interp, size, obj, newfunc) < 0)
426
0
    {
427
0
        return -1;
428
0
    }
429
0
    _PyBytes_data_t *data = (_PyBytes_data_t *)xidata->data;
430
0
    if (_PyBytes_GetData(obj, data) < 0) {
431
0
        _PyXIData_Clear(tstate->interp, xidata);
432
0
        return -1;
433
0
    }
434
0
    return 0;
435
0
}
436
437
int
438
_PyBytes_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
439
0
{
440
0
    if (!PyBytes_Check(obj)) {
441
0
        PyErr_Format(PyExc_TypeError, "expected bytes, got %R", obj);
442
0
        return -1;
443
0
    }
444
0
    size_t size = sizeof(_PyBytes_data_t);
445
0
    return _bytes_shared(tstate, obj, size, _PyBytes_FromXIData, xidata);
446
0
}
447
448
_PyBytes_data_t *
449
_PyBytes_GetXIDataWrapped(PyThreadState *tstate,
450
                          PyObject *obj, size_t size, xid_newobjfunc newfunc,
451
                          _PyXIData_t *xidata)
452
0
{
453
0
    if (!PyBytes_Check(obj)) {
454
0
        PyErr_Format(PyExc_TypeError, "expected bytes, got %R", obj);
455
0
        return NULL;
456
0
    }
457
0
    if (size < sizeof(_PyBytes_data_t)) {
458
0
        PyErr_Format(PyExc_ValueError, "expected size >= %d, got %d",
459
0
                     sizeof(_PyBytes_data_t), size);
460
0
        return NULL;
461
0
    }
462
0
    if (newfunc == NULL) {
463
0
        if (size == sizeof(_PyBytes_data_t)) {
464
0
            PyErr_SetString(PyExc_ValueError, "missing new_object func");
465
0
            return NULL;
466
0
        }
467
0
        newfunc = _PyBytes_FromXIData;
468
0
    }
469
0
    if (_bytes_shared(tstate, obj, size, newfunc, xidata) < 0) {
470
0
        return NULL;
471
0
    }
472
0
    return (_PyBytes_data_t *)xidata->data;
473
0
}
474
475
// str
476
477
struct _shared_str_data {
478
    int kind;
479
    const void *buffer;
480
    Py_ssize_t len;
481
};
482
483
static PyObject *
484
_new_str_object(_PyXIData_t *xidata)
485
0
{
486
0
    struct _shared_str_data *shared = (struct _shared_str_data *)(xidata->data);
487
0
    return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len);
488
0
}
489
490
static int
491
_str_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
492
0
{
493
0
    if (_PyXIData_InitWithSize(
494
0
            xidata, tstate->interp, sizeof(struct _shared_str_data), obj,
495
0
            _new_str_object
496
0
            ) < 0)
497
0
    {
498
0
        return -1;
499
0
    }
500
0
    struct _shared_str_data *shared = (struct _shared_str_data *)xidata->data;
501
0
    shared->kind = PyUnicode_KIND(obj);
502
0
    shared->buffer = PyUnicode_DATA(obj);
503
0
    shared->len = PyUnicode_GET_LENGTH(obj);
504
0
    return 0;
505
0
}
506
507
// int
508
509
static PyObject *
510
_new_long_object(_PyXIData_t *xidata)
511
0
{
512
0
    return PyLong_FromSsize_t((Py_ssize_t)(xidata->data));
513
0
}
514
515
static int
516
_long_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
517
0
{
518
    /* Note that this means the size of shareable ints is bounded by
519
     * sys.maxsize.  Hence on 32-bit architectures that is half the
520
     * size of maximum shareable ints on 64-bit.
521
     */
522
0
    Py_ssize_t value = PyLong_AsSsize_t(obj);
523
0
    if (value == -1 && PyErr_Occurred()) {
524
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
525
0
            PyErr_SetString(PyExc_OverflowError, "try sending as bytes");
526
0
        }
527
0
        return -1;
528
0
    }
529
0
    _PyXIData_Init(xidata, tstate->interp, (void *)value, NULL, _new_long_object);
530
    // xidata->obj and xidata->free remain NULL
531
0
    return 0;
532
0
}
533
534
// float
535
536
static PyObject *
537
_new_float_object(_PyXIData_t *xidata)
538
0
{
539
0
    double * value_ptr = xidata->data;
540
0
    return PyFloat_FromDouble(*value_ptr);
541
0
}
542
543
static int
544
_float_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
545
0
{
546
0
    if (_PyXIData_InitWithSize(
547
0
            xidata, tstate->interp, sizeof(double), NULL,
548
0
            _new_float_object
549
0
            ) < 0)
550
0
    {
551
0
        return -1;
552
0
    }
553
0
    double *shared = (double *)xidata->data;
554
0
    *shared = PyFloat_AsDouble(obj);
555
0
    return 0;
556
0
}
557
558
// None
559
560
static PyObject *
561
_new_none_object(_PyXIData_t *xidata)
562
0
{
563
    // XXX Singleton refcounts are problematic across interpreters...
564
0
    return Py_NewRef(Py_None);
565
0
}
566
567
static int
568
_none_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
569
0
{
570
0
    _PyXIData_Init(xidata, tstate->interp, NULL, NULL, _new_none_object);
571
    // xidata->data, xidata->obj and xidata->free remain NULL
572
0
    return 0;
573
0
}
574
575
// bool
576
577
static PyObject *
578
_new_bool_object(_PyXIData_t *xidata)
579
0
{
580
0
    if (xidata->data){
581
0
        Py_RETURN_TRUE;
582
0
    }
583
0
    Py_RETURN_FALSE;
584
0
}
585
586
static int
587
_bool_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
588
0
{
589
0
    _PyXIData_Init(xidata, tstate->interp,
590
0
            (void *) (Py_IsTrue(obj) ? (uintptr_t) 1 : (uintptr_t) 0), NULL,
591
0
            _new_bool_object);
592
    // xidata->obj and xidata->free remain NULL
593
0
    return 0;
594
0
}
595
596
// tuple
597
598
struct _shared_tuple_data {
599
    Py_ssize_t len;
600
    _PyXIData_t **items;
601
};
602
603
static PyObject *
604
_new_tuple_object(_PyXIData_t *xidata)
605
0
{
606
0
    struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(xidata->data);
607
0
    PyObject *tuple = PyTuple_New(shared->len);
608
0
    if (tuple == NULL) {
609
0
        return NULL;
610
0
    }
611
612
0
    for (Py_ssize_t i = 0; i < shared->len; i++) {
613
0
        PyObject *item = _PyXIData_NewObject(shared->items[i]);
614
0
        if (item == NULL){
615
0
            Py_DECREF(tuple);
616
0
            return NULL;
617
0
        }
618
0
        PyTuple_SET_ITEM(tuple, i, item);
619
0
    }
620
0
    return tuple;
621
0
}
622
623
static void
624
_tuple_shared_free(void* data)
625
0
{
626
0
    struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data);
627
#ifndef NDEBUG
628
    int64_t interpid = PyInterpreterState_GetID(_PyInterpreterState_GET());
629
#endif
630
0
    for (Py_ssize_t i = 0; i < shared->len; i++) {
631
0
        if (shared->items[i] != NULL) {
632
0
            assert(_PyXIData_INTERPID(shared->items[i]) == interpid);
633
0
            _PyXIData_Release(shared->items[i]);
634
0
            PyMem_RawFree(shared->items[i]);
635
0
            shared->items[i] = NULL;
636
0
        }
637
0
    }
638
0
    PyMem_Free(shared->items);
639
0
    PyMem_RawFree(shared);
640
0
}
641
642
static int
643
_tuple_shared(PyThreadState *tstate, PyObject *obj, xidata_fallback_t fallback,
644
              _PyXIData_t *xidata)
645
0
{
646
0
    Py_ssize_t len = PyTuple_GET_SIZE(obj);
647
0
    if (len < 0) {
648
0
        return -1;
649
0
    }
650
0
    struct _shared_tuple_data *shared = PyMem_RawMalloc(sizeof(struct _shared_tuple_data));
651
0
    if (shared == NULL){
652
0
        PyErr_NoMemory();
653
0
        return -1;
654
0
    }
655
656
0
    shared->len = len;
657
0
    shared->items = (_PyXIData_t **) PyMem_Calloc(shared->len, sizeof(_PyXIData_t *));
658
0
    if (shared->items == NULL) {
659
0
        PyErr_NoMemory();
660
0
        return -1;
661
0
    }
662
663
0
    for (Py_ssize_t i = 0; i < shared->len; i++) {
664
0
        _PyXIData_t *xidata_i = _PyXIData_New();
665
0
        if (xidata_i == NULL) {
666
0
            goto error;  // PyErr_NoMemory already set
667
0
        }
668
0
        PyObject *item = PyTuple_GET_ITEM(obj, i);
669
670
0
        int res = -1;
671
0
        if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) {
672
0
            res = _PyObject_GetXIData(tstate, item, fallback, xidata_i);
673
0
            _Py_LeaveRecursiveCallTstate(tstate);
674
0
        }
675
0
        if (res < 0) {
676
0
            PyMem_RawFree(xidata_i);
677
0
            goto error;
678
0
        }
679
0
        shared->items[i] = xidata_i;
680
0
    }
681
0
    _PyXIData_Init(xidata, tstate->interp, shared, obj, _new_tuple_object);
682
0
    _PyXIData_SET_FREE(xidata, _tuple_shared_free);
683
0
    return 0;
684
685
0
error:
686
0
    _tuple_shared_free(shared);
687
0
    return -1;
688
0
}
689
690
// code
691
692
PyObject *
693
_PyCode_FromXIData(_PyXIData_t *xidata)
694
0
{
695
0
    return _PyMarshal_ReadObjectFromXIData(xidata);
696
0
}
697
698
int
699
_PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
700
0
{
701
0
    if (!PyCode_Check(obj)) {
702
0
        _PyXIData_FormatNotShareableError(tstate, "expected code, got %R", obj);
703
0
        return -1;
704
0
    }
705
0
    if (_PyMarshal_GetXIData(tstate, obj, xidata) < 0) {
706
0
        return -1;
707
0
    }
708
0
    assert(_PyXIData_CHECK_NEW_OBJECT(xidata, _PyMarshal_ReadObjectFromXIData));
709
0
    _PyXIData_SET_NEW_OBJECT(xidata, _PyCode_FromXIData);
710
0
    return 0;
711
0
}
712
713
// function
714
715
PyObject *
716
_PyFunction_FromXIData(_PyXIData_t *xidata)
717
0
{
718
    // For now "stateless" functions are the only ones we must accommodate.
719
720
0
    PyObject *code = _PyMarshal_ReadObjectFromXIData(xidata);
721
0
    if (code == NULL) {
722
0
        return NULL;
723
0
    }
724
    // Create a new function.
725
    // For stateless functions (no globals) we use __main__ as __globals__,
726
    // just like we do for builtins like exec().
727
0
    assert(PyCode_Check(code));
728
0
    PyThreadState *tstate = _PyThreadState_GET();
729
0
    PyObject *globals = _PyEval_GetGlobalsFromRunningMain(tstate);  // borrowed
730
0
    if (globals == NULL) {
731
0
        if (_PyErr_Occurred(tstate)) {
732
0
            Py_DECREF(code);
733
0
            return NULL;
734
0
        }
735
0
        globals = PyDict_New();
736
0
        if (globals == NULL) {
737
0
            Py_DECREF(code);
738
0
            return NULL;
739
0
        }
740
0
    }
741
0
    else {
742
0
        Py_INCREF(globals);
743
0
    }
744
0
    if (_PyEval_EnsureBuiltins(tstate, globals, NULL) < 0) {
745
0
        Py_DECREF(code);
746
0
        Py_DECREF(globals);
747
0
        return NULL;
748
0
    }
749
0
    PyObject *func = PyFunction_New(code, globals);
750
0
    Py_DECREF(code);
751
0
    Py_DECREF(globals);
752
0
    return func;
753
0
}
754
755
int
756
_PyFunction_GetXIData(PyThreadState *tstate, PyObject *func,
757
                      _PyXIData_t *xidata)
758
0
{
759
0
    if (!PyFunction_Check(func)) {
760
0
        const char *msg = "expected a function, got %R";
761
0
        format_notshareableerror(tstate, NULL, 0, msg, func);
762
0
        return -1;
763
0
    }
764
0
    if (_PyFunction_VerifyStateless(tstate, func) < 0) {
765
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
766
0
        assert(cause != NULL);
767
0
        const char *msg = "only stateless functions are shareable";
768
0
        set_notshareableerror(tstate, cause, 0, msg);
769
0
        Py_DECREF(cause);
770
0
        return -1;
771
0
    }
772
0
    PyObject *code = PyFunction_GET_CODE(func);
773
774
    // Ideally code objects would be immortal and directly shareable.
775
    // In the meantime, we use marshal.
776
0
    if (_PyMarshal_GetXIData(tstate, code, xidata) < 0) {
777
0
        return -1;
778
0
    }
779
    // Replace _PyMarshal_ReadObjectFromXIData.
780
    // (_PyFunction_FromXIData() will call it.)
781
0
    _PyXIData_SET_NEW_OBJECT(xidata, _PyFunction_FromXIData);
782
0
    return 0;
783
0
}
784
785
786
// registration
787
788
static void
789
_register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
790
16
{
791
16
#define REGISTER(TYPE, GETDATA) \
792
96
    _xidregistry_add_type(xidregistry, (PyTypeObject *)TYPE, \
793
96
                          ((_PyXIData_getdata_t){.basic=(GETDATA)}))
794
16
#define REGISTER_FALLBACK(TYPE, GETDATA) \
795
16
    _xidregistry_add_type(xidregistry, (PyTypeObject *)TYPE, \
796
16
                          ((_PyXIData_getdata_t){.fallback=(GETDATA)}))
797
    // None
798
16
    if (REGISTER(Py_TYPE(Py_None), _none_shared) != 0) {
799
0
        Py_FatalError("could not register None for cross-interpreter sharing");
800
0
    }
801
802
    // int
803
16
    if (REGISTER(&PyLong_Type, _long_shared) != 0) {
804
0
        Py_FatalError("could not register int for cross-interpreter sharing");
805
0
    }
806
807
    // bytes
808
16
    if (REGISTER(&PyBytes_Type, _PyBytes_GetXIData) != 0) {
809
0
        Py_FatalError("could not register bytes for cross-interpreter sharing");
810
0
    }
811
812
    // str
813
16
    if (REGISTER(&PyUnicode_Type, _str_shared) != 0) {
814
0
        Py_FatalError("could not register str for cross-interpreter sharing");
815
0
    }
816
817
    // bool
818
16
    if (REGISTER(&PyBool_Type, _bool_shared) != 0) {
819
0
        Py_FatalError("could not register bool for cross-interpreter sharing");
820
0
    }
821
822
    // float
823
16
    if (REGISTER(&PyFloat_Type, _float_shared) != 0) {
824
0
        Py_FatalError("could not register float for cross-interpreter sharing");
825
0
    }
826
827
    // tuple
828
16
    if (REGISTER_FALLBACK(&PyTuple_Type, _tuple_shared) != 0) {
829
0
        Py_FatalError("could not register tuple for cross-interpreter sharing");
830
0
    }
831
832
    // For now, we do not register PyCode_Type or PyFunction_Type.
833
16
#undef REGISTER
834
16
#undef REGISTER_FALLBACK
835
16
}