Skip to content

Commit

Permalink
Merge branch 'main' into issue_125038_get_iter_rework
Browse files Browse the repository at this point in the history
  • Loading branch information
efimov-mikhail authored Nov 7, 2024
2 parents ee94916 + 09d6f5d commit 6c2770d
Show file tree
Hide file tree
Showing 49 changed files with 1,216 additions and 778 deletions.
15 changes: 7 additions & 8 deletions .github/workflows/jit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- x86_64-pc-windows-msvc/msvc
- aarch64-pc-windows-msvc/msvc
- x86_64-apple-darwin/clang
# - aarch64-apple-darwin/clang
- aarch64-apple-darwin/clang
- x86_64-unknown-linux-gnu/gcc
- x86_64-unknown-linux-gnu/clang
- aarch64-unknown-linux-gnu/gcc
Expand All @@ -79,11 +79,10 @@ jobs:
architecture: x86_64
runner: macos-13
compiler: clang
# GH-126464: A recent change to either GHA or LLVM broke this job:
# - target: aarch64-apple-darwin/clang
# architecture: aarch64
# runner: macos-14
# compiler: clang
- target: aarch64-apple-darwin/clang
architecture: aarch64
runner: macos-14
compiler: clang
- target: x86_64-unknown-linux-gnu/gcc
architecture: x86_64
runner: ubuntu-22.04
Expand Down Expand Up @@ -132,8 +131,8 @@ jobs:
brew update
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew install llvm@${{ matrix.llvm }}
SDKROOT="$(xcrun --show-sdk-path)" \
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
export SDKROOT="$(xcrun --show-sdk-path)"
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
make all --jobs 4
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
Expand Down
14 changes: 7 additions & 7 deletions Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2230,7 +2230,7 @@ This is done by filling a :c:type:`PyType_Spec` structure and calling
.. _number-structs:

Number Object Structures
========================
------------------------

.. sectionauthor:: Amaury Forgeot d'Arc

Expand Down Expand Up @@ -2344,7 +2344,7 @@ Number Object Structures
.. _mapping-structs:

Mapping Object Structures
=========================
-------------------------

.. sectionauthor:: Amaury Forgeot d'Arc

Expand Down Expand Up @@ -2381,7 +2381,7 @@ Mapping Object Structures
.. _sequence-structs:

Sequence Object Structures
==========================
--------------------------

.. sectionauthor:: Amaury Forgeot d'Arc

Expand Down Expand Up @@ -2461,7 +2461,7 @@ Sequence Object Structures
.. _buffer-structs:

Buffer Object Structures
========================
------------------------

.. sectionauthor:: Greg J. Stein <[email protected]>
.. sectionauthor:: Benjamin Peterson
Expand Down Expand Up @@ -2556,7 +2556,7 @@ Buffer Object Structures


Async Object Structures
=======================
-----------------------

.. sectionauthor:: Yury Selivanov <[email protected]>

Expand Down Expand Up @@ -2624,7 +2624,7 @@ Async Object Structures
.. _slot-typedefs:

Slot Type typedefs
==================
------------------

.. c:type:: PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Expand Down Expand Up @@ -2733,7 +2733,7 @@ Slot Type typedefs
.. _typedef-examples:

Examples
========
--------

The following are simple examples of Python type definitions. They
include common usage you may encounter. Some demonstrate tricky corner
Expand Down
7 changes: 2 additions & 5 deletions Doc/howto/logging-cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1267,11 +1267,8 @@ to adapt in your own applications.

You could also write your own handler which uses the :class:`~multiprocessing.Lock`
class from the :mod:`multiprocessing` module to serialize access to the
file from your processes. The existing :class:`FileHandler` and subclasses do
not make use of :mod:`multiprocessing` at present, though they may do so in the
future. Note that at present, the :mod:`multiprocessing` module does not provide
working lock functionality on all platforms (see
https://bugs.python.org/issue3770).
file from your processes. The stdlib :class:`FileHandler` and subclasses do
not make use of :mod:`multiprocessing`.

.. currentmodule:: logging.handlers

Expand Down
114 changes: 46 additions & 68 deletions Include/internal/pycore_crossinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,28 @@ extern int _Py_CallInInterpreterAndRawFree(
/* cross-interpreter data */
/**************************/

typedef struct _xid _PyCrossInterpreterData;
typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *);
typedef struct _xid _PyXIData_t;
typedef PyObject *(*xid_newobjectfunc)(_PyXIData_t *);
typedef void (*xid_freefunc)(void *);

// _PyCrossInterpreterData is similar to Py_buffer as an effectively
// _PyXIData_t is similar to Py_buffer as an effectively
// opaque struct that holds data outside the object machinery. This
// is necessary to pass safely between interpreters in the same process.
struct _xid {
// data is the cross-interpreter-safe derivation of a Python object
// (see _PyObject_GetCrossInterpreterData). It will be NULL if the
// (see _PyObject_GetXIData). It will be NULL if the
// new_object func (below) encodes the data.
void *data;
// obj is the Python object from which the data was derived. This
// is non-NULL only if the data remains bound to the object in some
// way, such that the object must be "released" (via a decref) when
// the data is released. In that case the code that sets the field,
// likely a registered "crossinterpdatafunc", is responsible for
// likely a registered "xidatafunc", is responsible for
// ensuring it owns the reference (i.e. incref).
PyObject *obj;
// interp is the ID of the owning interpreter of the original
// object. It corresponds to the active interpreter when
// _PyObject_GetCrossInterpreterData() was called. This should only
// _PyObject_GetXIData() was called. This should only
// be set by the cross-interpreter machinery.
//
// We use the ID rather than the PyInterpreterState to avoid issues
Expand All @@ -77,96 +77,77 @@ struct _xid {
// okay (e.g. bytes) and for those types this field should be set
// to NULL. However, for most the data was allocated just for
// cross-interpreter use, so it must be freed when
// _PyCrossInterpreterData_Release is called or the memory will
// _PyXIData_Release is called or the memory will
// leak. In that case, at the very least this field should be set
// to PyMem_RawFree (the default if not explicitly set to NULL).
// The call will happen with the original interpreter activated.
xid_freefunc free;
};

PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void);
PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data);
PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void);
PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);

#define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data)
#define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj)
#define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid)
#define _PyXIData_DATA(DATA) ((DATA)->data)
#define _PyXIData_OBJ(DATA) ((DATA)->obj)
#define _PyXIData_INTERPID(DATA) ((DATA)->interpid)
// Users should not need getters for "new_object" or "free".


/* getting cross-interpreter data */

typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);

typedef struct _xid_lookup_state _PyXIData_lookup_t;

PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *);
PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *);
PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *);


/* using cross-interpreter data */

PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);
PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);
PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);


/* defining cross-interpreter data */

PyAPI_FUNC(void) _PyCrossInterpreterData_Init(
_PyCrossInterpreterData *data,
PyAPI_FUNC(void) _PyXIData_Init(
_PyXIData_t *data,
PyInterpreterState *interp, void *shared, PyObject *obj,
xid_newobjectfunc new_object);
PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize(
_PyCrossInterpreterData *,
PyAPI_FUNC(int) _PyXIData_InitWithSize(
_PyXIData_t *,
PyInterpreterState *interp, const size_t, PyObject *,
xid_newobjectfunc);
PyAPI_FUNC(void) _PyCrossInterpreterData_Clear(
PyInterpreterState *, _PyCrossInterpreterData *);
PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);

// Normally the Init* functions are sufficient. The only time
// additional initialization might be needed is to set the "free" func,
// though that should be infrequent.
#define _PyCrossInterpreterData_SET_FREE(DATA, FUNC) \
#define _PyXIData_SET_FREE(DATA, FUNC) \
do { \
(DATA)->free = (FUNC); \
} while (0)
// Additionally, some shareable types are essentially light wrappers
// around other shareable types. The crossinterpdatafunc of the wrapper
// around other shareable types. The xidatafunc of the wrapper
// can often be implemented by calling the wrapped object's
// crossinterpdatafunc and then changing the "new_object" function.
// We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that,
// xidatafunc and then changing the "new_object" function.
// We have _PyXIData_SET_NEW_OBJECT() here for that,
// but might be better to have a function like
// _PyCrossInterpreterData_AdaptToWrapper() instead.
#define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \
// _PyXIData_AdaptToWrapper() instead.
#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \
do { \
(DATA)->new_object = (FUNC); \
} while (0)


/* using cross-interpreter data */

PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);
PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *);
PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *);
PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);
PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *);


/* cross-interpreter data registry */

// For now we use a global registry of shareable classes. An
// alternative would be to add a tp_* slot for a class's
// crossinterpdatafunc. It would be simpler and more efficient.

typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *,
_PyCrossInterpreterData *);

struct _xidregitem;

struct _xidregitem {
struct _xidregitem *prev;
struct _xidregitem *next;
/* This can be a dangling pointer, but only if weakref is set. */
PyTypeObject *cls;
/* This is NULL for builtin types. */
PyObject *weakref;
size_t refcount;
crossinterpdatafunc getdata;
};

struct _xidregistry {
int global; /* builtin types or heap types */
int initialized;
PyMutex mutex;
struct _xidregitem *head;
};

PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc);
PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *);
PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H
#include "pycore_crossinterp_data_registry.h"
#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H


/*****************************/
Expand All @@ -175,22 +156,19 @@ PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);

struct _xi_runtime_state {
// builtin types
// XXX Remove this field once we have a tp_* slot.
struct _xidregistry registry;
_PyXIData_lookup_t data_lookup;
};

struct _xi_state {
// heap types
// XXX Remove this field once we have a tp_* slot.
struct _xidregistry registry;
_PyXIData_lookup_t data_lookup;

// heap types
PyObject *PyExc_NotShareableError;
};

extern PyStatus _PyXI_Init(PyInterpreterState *interp);
extern void _PyXI_Fini(PyInterpreterState *interp);

extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
extern void _PyXI_FiniTypes(PyInterpreterState *interp);

Expand Down
36 changes: 36 additions & 0 deletions Include/internal/pycore_crossinterp_data_registry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef Py_CORE_CROSSINTERP_DATA_REGISTRY_H
# error "this header must not be included directly"
#endif


// For now we use a global registry of shareable classes. An
// alternative would be to add a tp_* slot for a class's
// xidatafunc. It would be simpler and more efficient.

struct _xidregitem;

struct _xidregitem {
struct _xidregitem *prev;
struct _xidregitem *next;
/* This can be a dangling pointer, but only if weakref is set. */
PyTypeObject *cls;
/* This is NULL for builtin types. */
PyObject *weakref;
size_t refcount;
xidatafunc getdata;
};

struct _xidregistry {
int global; /* builtin types or heap types */
int initialized;
PyMutex mutex;
struct _xidregitem *head;
};

PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc);
PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *);

struct _xid_lookup_state {
// XXX Remove this field once we have a tp_* slot.
struct _xidregistry registry;
};
6 changes: 4 additions & 2 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ extern PyTypeObject _PyExc_MemoryError;
.next_id = -1, \
}, \
.xi = { \
.registry = { \
.global = 1, \
.data_lookup = { \
.registry = { \
.global = 1, \
}, \
}, \
}, \
/* A TSS key must be initialized with Py_tss_NEEDS_INIT \
Expand Down
Loading

0 comments on commit 6c2770d

Please sign in to comment.